Dart - tutorial - before Flutter project
Before starting Flutter project , Dart basic!
var
Dart declares variables similarly to Java, but unlike Java, type inference is possible.
var friend = 'taelab';
friend = 23; // Error: Compilation failed.
By the way, Dart also has a dynamic type that can change its type.
dynamic
In the case of dynamic, the type can be inferred like var, and the type can also be changed. In addition, since dynamic is supported in parameters, there is no need to specify the type.
dynamic a= 'tae';
a= 121342;
Type casting and num
In Java, large types are automatically type-casted without explicitly type-casting small types, but in the case of Dart, type-casting is required.
int n = 2;
// Error: Compilation failed.
double m = n;
int n = 1;
double m = n as double; //ok
In the case of int and double, they can also be declared as supertype num.
num a = 1;
num b = 1.11;
final / const
In common, both final and const cannot be changed once declared. A value defined as final can be set as a value defined at runtime, but a value defined as const cannot be set as a value defined at runtime.
Collections
Dart provides collections such as List, Map, and Set, but does not provide an array data structure.
// List
List<int> setNums = [1,2,3,4,5];
var nums2 = [1, 2, 3]; // Type inferred
var nums3 = [1, 2, 3 ,4, if (true) 5]; //condition in List
var friends = ['a','b','c'];
var new_friends = ['d','e','f', for (var friend in friends ) "- ${friend}"];
// set
Set<int> setNums = {1,2,3,4,4,4,4,66,6};
var setNums2 = {1,5,5,4,6,4,3,3,5,5,5,1,5,5,2,2,2}; // Type inferred
// map
Map<String, int> mapNums = {
"key" : 1,
"key2" : 2
};
var mapNums2 = { // Type inferred
"key" : 1,
"key2" : 2
};
var nums = {
}
When declaring set and map through var, if nothing is written inside {}, var is inferred as map type.
Spread operator ...
// (...)
var a = [1,2,3,4,6];
var b = [...a, 5, 7];
function declaration
Since the type of the parameter is inferred as dynamic, there is no need to specify the data type.
add(num1, num2){
return num1 + num2;
}
optional parameter
Optional parameters allow optional use of parameters wrapped in {} when defining a function.
add(num1, {num2}){
return num1 + num2;
}
print(add(1, num2 : 3));
If you want to return a value other than null as for optional parameter, you can give it a default value.
add(num1, {num2 = 3}){
return num1 + num2;
}
function and QQ operator
// name parameter can be null.
String capitalizeName(String? name) => name != null
? name.toUpperCase() : 'ANON'
String capitalizeName(String? name) => name?.toUpperCase() ?? 'ANON'
QQ operator
void main () {
String? name;
name ??= 'a';
name ?? ='another';
print(name); // a
}
Asynchronous processing - Future, async, await
A Future promises to receive the result of a certain task later, and proceeds to the next task immediately without waiting for the result of the requested task. After that, when the task is completed, the asynchronous processing is executed by receiving the result value.
void main(){
print("start");
asyncFunc();
print("end");
}
Future asyncFunc() async{
await Future.delayed(Duration(seconds : 1));
print("1");
await Future.delayed(Duration(seconds : 1));
print("2");
await Future.delayed(Duration(seconds : 1));
print("3");
return;
}
Class
class Person {
final String name = 'tat';
int age;
getName(){
return name;
}
Person (String name, int age) {
this.name = name; // error since final String field
this.age = age;
}
}
class Person {
late final String name = 'tat';
//late means that the values of the variables will be retrieved later.
late int age;
getName(){
return this.name;
}
Person (String name, int age) {
this.name = name;
this.age = age;
}
}
void main () {
var person = Person ("taesik", 22);
}
Brief constructor + specified parameter + required
class Player {
final String name;
int age;
String team;
int point;
Player({
required this.name,
required this.age,
required this.team,
required this.point,
});
void greet() {
print('Hi my name is $name');
}
}
void main() {
//specified parameter key-value style
var player = Player (
name:"asd",
age: 22,
team: 'pncst',
point: 20000,
)
}
Brief field
class Player {
final String name, team;
int age,point;
Player({
required this.name,
required this.age,
required this.team,
required this.point,
});
void greet() {
print('Hi my name is $name');
}
}
void main() {
//specified parameter key-value style
var player = Player (
name:"asd",
age: 22,
team: 'pncst',
point: 20000,
)
}
late means that the values of the variables will be retrieved later.
Java uses the new keyword when creating an object, but Dart basically omits it.
The same role as Private in Java, but in Dart, Private is defined by appending _. In Java, private can be accessed only within the class, but in Dart, private variables can be accessed in the file where the class is defined.
Named Constructors
class Player {
final String name, team;
int age,point;
Player( {
required this.name,
required this.age,
required this.team,
required this.point,
}
);
Player.createBluePlayer({
required String name,
required int age
}) : this.age = age,
this.name = name,
this.team = 'blue',
this.xp = 0;
Player.createRedPlayer(String name, int age)
: this.age =age,
this.name = name,
this.team = 'red',
this.xp =0;
void greet() {
print('Hi my name is $name');
}
}
void main() {
//specified parameter key-value style
var player = Player (
name:"asd",
age: 22,
team: 'pncst',
point: 20000,
)
var player1 = Player.createBluePlayer(
name: 'brian',
age:21,
);
var redplayer = Player.createRedPlayer('tasdi',21);
}
Cascade Notation
class Player {
final String name, team;
int age,point;
Player( {
required this.name,
required this.age,
required this.team,
required this.point,
}
);
Player.createBluePlayer({
required String name,
required int age
}) : this.age = age,
this.name = name,
this.team = 'blue',
this.xp = 0;
Player.createRedPlayer(String name, int age)
: this.age =age,
this.name = name,
this.team = 'red',
this.xp =0;
void greet() {
print('Hi my name is $name');
}
}
void main() {
var taesik = Player(name: 'taesik', point:1000, age:22,team:'ada')
..name = 'asd'
..xp = 1200000
..team = 'blue';
var ted = Player(name: 'taesik', point:1000, age:22,team:'ada');
var clone = ted
..name = 'clone'
..xp = 12222
..team = 'blue'
..greet();
}
enums
enum Team {red,blue}
//
Team.blue
TEam.red
abstract class, abstract method
abstract class Human {
void walk;
}
class Player extends Human {
void walk() {
...
}
...
Inheritance + override method
class Human {
final String name;
Human(this.name);
void greet() {
print('hello');
}
}
enum Team {red,blue}
class Player extends Human {
final Team team;
Player({
required this.team,
required String name, //Forwarding to Human class
}) : super(name:name);
@override
void sayHello(){
super.sayHello();
print('and I want to win ${team}');
}
...
Mixins - (Class without constructor)
class Point {
final double level = 12121;
}
class QuickPlayer {
void doSomethingQuick() {
}
}
class Player with Point, QuicPlayer {
...
}
null safety - nullable, non-nullable
int a = 10;
a = null; // Error: Compilation failed.
int? h = 10;
h = null; // ok
A var type cannot be declared nullable. As explained above, type inference is possible for var types, so nullable and non-nullable are automatically inferred.
Null safety in dynamic types is meaningless. The dynamic type means that the value to be assigned is not limited, and all types of data can be assigned. Since all of these types also include nullable, being declared as a dynamic type is itself declared as nullable.
Type check - 'is'
int a = 1;
print(a is int); //true
print(a is! int); //false
anonymous function
(number) {
return number % 2 == 0;
};
Lambda
(number) => number%2 == 0;
typedef (type variable)
typedef listOfInts = List<int>;
listOfInts reverseListOfNumbers(listOfInts list) {
var reversed = list.reversed;
return reversed.toList();
}