Key concepts
Before learning about Dart, it is important to understand the following Dart-related concepts:
Everything that can be placed in a variable is an object, and every object is an instance of a class. Even numbers, functions, and null values are objects, and all objects inherit from the Object class.
Dart is a strongly typed language, but type marking is optional because Dart can infer types. To explicitly state that no types are required, the special type dynamic identifier can be used.
Dart supports generic types such as List or List (a list of objects of any type).
Dart supports top-level functions (e.g. the main function), as well as functions bound to classes or objects (static and instance methods, respectively). Functions can also be created inside functions (nested functions or native functions).
Dart supports top-level variables, as well as variables bound to classes or objects (static and instance variables, respectively).
Unlike Java, Dart does not have the keywords public, protected, and private.If you want to set private variables or functions, the variable and function names begin with an underscore (_).
Identifiers can begin with a letter or an underscore (_) followed by any combination of these characters plus a number.
Dart has two expressions (with runtime values) and statements (without). For example, the conditional expression condition? expr1: expr2 has the value expr1 or expr2. Compare this with an if-else statement, which has no value. Statements usually contain one or more expressions, but expressions cannot directly contain statements.
The Dart tool can report two kinds of problems: warnings and errors. Warnings are simply an indication that your code may not be working properly, but they do not prevent your program from executing. Errors can be compile-time or run-time. Compile-time errors prevent your code from executing; run-time errors cause an exception to be thrown during code execution.
Any language has keywords, which are words that cannot be used as identifiers while programming.The keywords of Dart are listed below:
Avoid using the above words as identifiers when coding; if necessary, use words with superscripts as identifiers:
Words with the superscript 1 are contextual keywords that have meaning only in a specific location; they are valid everywhere;
Words with superscript 2 are built-in identifiers; they are valid in most places, but cannot be used as class and type names or as an import prefix;
Words with superscript 3 are limited reserved characters associated with asynchronous support added after the release of Dart 1.0, and cannot use await and yield as identifiers in any function body labeled async, async * or sync *.
Definition of variables
1. You can use var to define a variable, and the type of the variable can be inferred from the value of the variable
var name = "hi";
var age = 18;
var high = 1.70;
As above, the type of the variable has already been determined after the definition of the variable, and no other type of value can be assigned to the variable.
var name = "hi";
name = 3;
2. Variables can also be defined using specific types
String name = "bruce";
int age = 18;
3. If the variable is not limited to a single type, you can define the variable using dynamic or Object
dynamic value = 18;
print("value = $value");
value = "bruce";
print("value = $value");
value = 3.5;
print("value = $value");
Object val = 18;
print("val = $val");
val = "bruce";
print("val = $val");
val = 3.5;
print("val = $val");
The output result is
value = 18
value = bruce
value = 3.5
val = 18
val = bruce
val = 3.5
Default values for variables
Since some of the previous concepts about Dart said that everything that can be put in a variable is an object, if a variable has no initialized value, then it defaults to null.
int value1;
print("value1 = $value1");
bool value2;
print("value2 = $value2");
var value3;
print("value3 = $value3");
dynamic value4;
print("value4 = $value4");
The output result is
value1 = null
value2 = null
value3 = null
value4 = null
final and const
If you don’t intend to change the variable, you can use either final or const. a final variable can only be set once, whereas const variables are compile-time constants and must be assigned a value when they are defined.
class Person {
static const desc = "This is a Person class";
final name;
Person(this.name);
}
Person p = Person("Bruce");
print("p.name = ${p.name}");
p.name = "haha";
Built-in type
The Dart language supports the following types
numbers
Contains two types, int and double, there is no float type like in Java, int and double are subtypes of num.strings
Dart’s string is a series of UTF-16 code units. The method of creation is as follows:
String str1 = "hello";
print("str1 = $str1");
String str2 = """Hi,Bruce
This is Xiaoming.
""";
print("str2 = $str2");
The output result is
str1 = hello
str2 = Hi,Bruce
This is Xiaoming.
booleans
Dart has a type named bool, and there are only two objects that have the bool type: true and false, both of which are compile-time constants.lists
As with collections common to other programming languages, the collections used in Dart are arrays or ordered groups of objects.Arrays in Dart are List objects.
List arr = ["Bruce", "Nick", "John"];
print("arr = $arr");
- maps
Map map = {
"name": "Bruce",
"age": 18,
"high": 1.70
};
print("map = $map");
print("map['name'] = ${map['name']}");
var map1 = {
1: "hi",
2: "hello",
3: "yep"
};
print("map1 = $map1");
print("map1[1] = ${map1[1]}");
The output result is
map = {name: Bruce, age: 18, high: 1.7}
map['name'] = Bruce
map1 = {1: hi, 2: hello, 3: yep}
map1[1] = hi
runes
Runes are UTF-32 code points for strings. Representing 32-bit Unicode values in a string requires special syntax, commonly used as \uXXXX, where XXXX is a 4-digit hexadecimal value, for example, a small heart (♥) is\u2665
. To specify more or less than 4 hexadecimal digits, put the value in curly brackets. For example, smile (😆) is\u{1f600}
.
String smile = '\u{1f600}';
print("222:$smile");
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(String.fromCharCodes(input));
The output result is
Dart is a true object-oriented language, so even functions are objects and have the type Function. this means that functions can be assigned to variables or passed as arguments to other functions.
Definition Methods
Like most programming languages, the Dart function is usually defined in the following way
String getName() {
return "Bruce";
}
If the function body contains only one expression, you can use the shorthand syntax
String getName() => "Bruce";
Optional parameters
The Dart function can set optional parameters, either named or positional.
Named parameters, defined in the format {param1, param2, …}
void showDesc({var name, var age}) {
if(name != null) {
print("name = $name");
}
if(age != null) {
print("age = $age");
}
}
showDesc(name: "Bruce");
name = Bruce
For positional parameters, use [] to mark optional parameters.
void showDesc(var name, [var age]) {
print("name = $name");
if(age != null) {
print("age = $age");
}
}
showDesc("Bruce");
name = Bruce
默认值
Optional arguments to a function can also be set to default values using =
void showDesc(var name, [var age = 18]) {
print("name = $name");
if(age != null) {
print("age = $age");
}
}
showDesc("Bruce");
name = Bruce
age = 18
main function
As with other programming languages, every application in Dart must have a top-level main() function that serves as the entry point to the application.
function as an argument
A function in Dart can be used as an argument to another function.
void println(String name) {
print("name = $name");
}
void showDesc(var name, Function log) {
log(name);
}
showDesc("Bruce", println);
name = Bruce
anonymous function
void showDesc(var name, Function log) {
log(name);
}
showDesc("Bruce", (name) {
print("name = $name");
});
name = Bruce
nested function
Dart supports nested functions, which means that functions can be defined within functions.
void showDesc(var name) {
print("That is a nested function!");
void println(var name) {
print("name = $name");
}
println(name);
}
showDesc("Bruce");
That is a nested function!
name = Bruce
The operators used in Dart are listed in the following table
Description | Operator |
---|---|
dollar suffix (linguistics) | expr++ expr-- () [] . ?. |
dollar prefix (linguistics) | -expr !expr ~expr ++expr --expr |
multiplication and division operations | * / % ~/ |
addition and subtraction operations | + - |
<< >> | |
& | |
palindromic or binomial (math.) | ^ |
| | |
Comparative Relationships and Type Judgments | >= > <= < as is is! |
== != | |
&& | |
|| | |
Whether null | ?? |
conditional statement operation | expr1 ? expr2 : expr3 |
cascade operation | .. |
Distribution assignment operation | = *= /= ~/= %= += -= <<= >>= &= ^= |= ??= |
The following is an introduction to some unused operators for Java or Objective-C by code.
-
?.
utilization
class Person {
var name;
Person(this.name);
}
Person p;
var name = p?.name;
print("name = $name");
name = null
-
~/
utilization
var num = 10;
var result = num ~/ 3;
print("result = $result");
result = 3
-
as
The use of as for type conversion
class Banana {
var weight;
Banana(this.weight);
}
class Apple {
var weight;
Apple(this.weight);
}
dynamic b = Banana(20);
(b as Banana).weight = 20;
print("b.weight = ${(b as Banana).weight}");
(b as Apple).weight = 30;
print("b.weight = ${(b as Apple).weight}");
b.weight = 20
Uncaught exception:
CastError: Instance of 'Banana': type 'Banana' is not a subtype of type 'Apple'
-
is
utilization
getFruit() => Banana(20);
class Banana {
var weight;
Banana(this.weight);
}
class Apple {
var color;
Apple(this.color);
}
var b = getFruit();
if(b is Apple) {
print("The fruit is an apple");
} else if(b is Banana) {
print("The fruit is a banana");
}
The fruit is a banana
-
??
utilization
String name;
String nickName = name ?? "Nick";
print("nickName = $nickName");
name = "Bruce";
nickName = name ?? "Nick";
print("nickName = $nickName");
nickName = Nick
nickName = Bruce
..
of use, cascading operations allow a series of operations to be performed on the same object.
class Banana {
var weight;
var color;
Banana(this.weight, this.color);
void showWeight() {
print("weight = $weight");
}
void showColor() {
print("color = $color");
}
}
Banana(20, 'yellow')
..showWeight()
..showColor();
weight = 20
color = yellow
control flow statement
Control flow statements in Dart, like any other language, contain the following methods
- if and else
- for loop
- While and do-while loops
- break and continue
- switch-case语句
The above control flow statements are the same as other programming language usage, switch-case has a special usage as follows, you can use continue statement and label to execute the specified case statement.
var fruit = 'apple';
switch (fruit) {
case 'banana':
print("this is a banana");
continue anotherFruit;
anotherFruit:
case 'apple':
print("this is an apple");
break;
}
this is an apple
Dart’s exception catching also uses the try-catch syntax, although it is slightly different from languages such as java
void handleOperator() => throw Exception("this operator exception!");
try {
handleOperator();
} on Exception catch(e) {
print(e);
} finally {
print("finally");
}
Exception: this operator exception!
finally
Dart is an object-oriented language with classes and mixin-based inheritance. Like Java, all classes in Dart inherit from Object.
constructor
Dart’s constructor is the same as normal function, it can define no-parameter and parameter, named parameter and positional parameter, optional parameter and set default value for optional parameter, etc. Dart’s constructor has the following features:
- Named constructors can be defined
- You can initialize instance variables before the function body runs
Subclasses do not inherit constructors from their parents, and subclasses defined without constructors only have constructors with no parameters and no names
Subclasses defining constructors inherit from the parent class by default with no parameters, or they can inherit from a constructor that is specified with parameters;
Initialize instance variables before running named constructors and function bodies
class Tree {
var desc;
Tree.init() {
desc = "this is a seed";
}
Tree(var des) : desc = des;
}
Tree t = Tree.init();
print("${t.desc}");
Tree t1 = Tree("this is a tree");
print("${t1.desc}");
this is a seed
this is a tree
Constructor inheritance
class Fruit {
Fruit() {
print("this is Fruit constructor with no param");
}
Fruit.desc(var desc) {
print("$desc in Fruit");
}
}
class Apple extends Fruit {
Apple():super() {
print("this is Apple constructor with no param");
}
Apple.desc(var desc) {
print('$desc in Apple');
}
}
Apple();
Apple.desc("say hello");
this is Fruit constructor with no param
this is Apple constructor with no param
this is Fruit constructor with no param
say hello in Apple
Mixin inheritance
A mixin is a way to reuse class code across multiple class hierarchies.
class LogUtil {
void log() {
print("this is a log");
}
}
class Fruit {
Fruit() {
print("this is Fruit constructor with no param");
}
}
class Apple extends Fruit with LogUtil {
Apple():super() {
print("this is Apple constructor with no param");
}
}
Apple a = Apple();
a.log();
this is Fruit constructor with no param
this is Apple constructor with no param
this is a log
Dart, like Java, supports generics.
class Apple {
var desc;
Apple(this.desc);
void log() {
print("${this.desc}");
}
}
class Banana {
var desc;
Banana(this.desc);
void log() {
print("${this.desc}");
}
}
class FruitFactory<T> {
T produceFruit(T t) {
return t;
}
}
FruitFactory<Banana> f = FruitFactory<Banana>();
Banana b = f.produceFruit(Banana("a banana"));
b.log();
FruitFactory<Apple> f1 = FruitFactory<Apple>();
Apple a = f1.produceFruit(Apple("an apple"));
a.log();
a banana
an apple