Recently the company is ready to start a new project, through technical team some research, decided to develop the first version of Flutter App, pretending to text, often to review the review. As the project using agile development model, it is mainly used paper summarizes and records Dart grammar, more advanced and rare usage will occasionally update later in the development process.
First of all
Before we contacted Dart grammar, we need to bear in mind the following, which will be the follow-up Dart grammar learning, understanding and application of great help:
- Everything is objects , each object is an instance of a class. In Dart, the even numbers, methods, and
null
are objects, and all objects are inherited from the Object class. - Although the Dart language is a strongly typed language, but you still can not specify the type in the type declaration, because Dart type inference can be made automatically. As the code
var number = 5;
, thenumber
type of the variable to be inferredint
, when you do not want to explicitly declare types, you can use a specific type of dynamic identified. - Dart also supports generic language, such as
List<int>
,List<dynamic>
(same in JavaList<Object>
). - Dart language support method top (i.e., not bound to the class method, the above
main
methods), and methods of binding class and instance (corresponding to static and instance methods), but also supports methods nested (with Python and JS) . - Likewise, the top supports Dart variables, and the variables defined in the class (e.g., static variables and instance variables).
- And Java is different, Dart is not
public
,protected
andprivate
keywords. Or a method by which the variable name with a_
prefix that identifies it as a private domain.
variable
You can var
or to modify a specific type of variable, if the variable type is not fixed, you can also dynamic
or Object
modified. Such as:
// 类型推断
var name = 'Bob';
// 指定类型
String name = 'Bob';
// 类型不局限于string
dynamic name = 'Bob';
Defaults
When Dart declared if uninitialized, will be automatically initialized to null
:
int lineCount;
assert(lineCount == null);
Note:
assert
only in the development environment, not with the actual production environment.
final and const
final
And const
identify the variables can only be assigned once, except that final
a run-time assignment, const
an assignment at compile time.
final String nickname = 'Jack';
// final修饰时, 可省略类型声明
final name = 'Jack';
const
Not only it can be used to declare variables can also be used to create a constant value, such as:
// 此时不能在对列表a进行更新操作
var a = const [1, 2];
// 注意以下 const 修饰的区别
var foo = const [];
const baz = []; // Equivalent to `const []`
...
foo = [1, 2, 3]; // Was const []
baz = [42]; // Error: Constant variables can't be assigned a value.
type of data
Dart language supported data types and Java similar, but also different, let's follow "common ground" law were to recognize them.
Digital Type
The Dart figures are only two types: Int and Double . Unlike Java it is that it does not provide float type. For example, we can define digital in the following ways:
// 定义整型
var x = 123;
var hex = 0xDEADBEEF;
// 定义双精度类型
var y = 1.199;
var exponents = 1.42e5;
Look at how the common data conversion performed:
// String -> int
var a = int.parse('1');
assert(a == 1);
// String -> double
var b = double.parse('1.1');
assert(b == 1.1);
// int -> String
String c = 1.toString();
assert(c == '1');
// double -> String
String d = 3.14159.toStringAsFixed(2);
assert(d == '3.14');
int
Type may be performed by conventional bit shift ( <<
, >>
), the AND ( &
) and OR ( |
) operator, such as:
assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 >> 1) == 1); // 0011 >> 1 == 0001
assert((3 | 4) == 7); // 0011 | 0100 == 0111
String type
Declaration string may be introduced by single or double quotes:
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";
By stitching strings +
or 换行
be implemented, such as:
var a = '123' + '456'
var b = '123'
'456';
assert(a == b)
print(a);
// Out: 123456
In addition, multiple lines may be modified by a triple quoted string (maintaining a specific format):
var s1 = '''
You can create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-line string.""";
Boolean
The Dart bool
type can if-else
either assert
be checked, such as:
// Check for an empty string.
var fullName = '';
assert(fullName.isEmpty);
// Check for zero.
var hitPoints = 0;
assert(hitPoints <= 0);
// Check for null.
var unicorn;
assert(unicorn == null);
// Check for NaN.
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);
Array type
In the Dart language, that is an array list, a list that is an array.
void main() {
var list = [1, 2, 3];
list.add(4);
list.remove(3);
list[1] = 5;
var last = list[list.length - 1];
print('list is $list');
print('last is $last');
}
Furthermore, you can …
or ...?
(avoiding empty exception) inserting a plurality of elements in bulk:
var list1 = [1, 2, 3];
var list2 = [0, ...list1];
var list3;
var list24 = [0, ...?list3];
In addition, can also if
or for
insert element conditions operator:
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet'
];
var listOfInts = [1, 2, 3];
var listOfStrings = [
'#0',
for (var i in listOfInts) '#$i'
];
assert(listOfStrings[1] == '#1');
Set and Map
The Dart Set is a collection of unordered unique items. To create an empty set, there are two ways:
var names = <String>{};
Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.
Create a constant Set the following ways:
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
// constantSet.add('helium'); // Uncommenting this causes an error.
As Map Data storage is the key, key
and value
can be of any type. You can create a Map in the following ways:
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
// 或者通过以下方式
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
function
Dart is a fully object-oriented language, even if it is a function object, and has its own type - Function
. This means that the function can be assigned to a variable or passed as an argument among other functions .
For expressions containing only a method body, you can also use the =>
short form, such as:
void say() {
print('123');
}
// 该写法与以上有同样效果
void say2() => print('123');
In addition, the same function type inference support, such as:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
// 与下面的效果一样
isNoble(atomicNumber) => _nobleGases[atomicNumber] != null;
Optional parameters
And kotlin language similar function Dart also supports optional parameters of this function, divided into named optional parameters and location of optional parameters , they can not be used in a function. But they all support the default parameter settings .
Named optional parameters
Named by braces optional parameters
{}
to specify the optional named parameters, such as:void main() { hello(name: 'Tom'); } void hello({@required String name='Jack', int age=18}) { print('Hello, my name is $name, i\'m $age years old.'); }
We can set default values for optional named parameters, if the value of the optional parameter is not specified, it will automatically use the default value when in use. In addition, we can
@required
to label those parameters do not want to be ignored.Location optional parameters
As the name suggests, the optional position parameter allows us to ignore certain arguments to a function, such as:
void main() { sayHello('Tom', 19); } void sayHello(String name, int age, [String hobby = null]) { var result = 'Hello, my name is $name, i\'m $age years old'; if (hobby != null) { result += ', my bobby is $hobby.'; } print(result); }
Anonymous function
Whatever the language, seems to be able to see the shadow of the anonymous function, we can simply declare an anonymous function in the following ways:
var loge = (msg) => Logger.print(Logger.Error, msg);
void main() {
loge("there has some errors");
}
Dart in the list to provide anonymous functions - forEach
such as:
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
Common operator
Dart offers many powerful operators, here are a few commonly used:
Type judgment
Such as:
is
the equivalent in Javainstanceof
Divisible
Such as:
a ~/ b
equivalent to(a /b) as int
Non-air-conditioning
Such as:
a?.b
the equivalent ofa == null ? null : a.b
Three head operations
Such as:
a??b
the equivalent ofa == null ? b : a
Trinocular assignment operator
Such as:
a ??= b
the equivalent ofa = a == null ? b : a
Type Conversion
Such as:
a as int
the equivalent in Java(int) a
Concatenation operator
Concatenation operator used
..
to represent an object is mainly used for continuous operation, in somewhat similar kotlin apply and let, such as:var button = Button(this); button.text = 'Confirm'; button.color = Color.parse("#f3f355"); button.onClick.listen((v) => toast('Confirmed')); // 等价于下面写法 Button(this) ..text = 'Confirm' // Use its members. ..color = Color.parse("#f3f355") ..onClick.listen((v) => toast('Confirmed'));
Exception Handling
Throws
Dart can be thrown in a non-null object (not just Exception
or Error
) as an exception. Thrown very simple way, just like this:
throw FormatException('Expected at least 1 section');
throw 'Out of llamas!';
void distanceTo(Point other) => throw UnimplementedError();
Catch the exception
We can try-on
capture a specific abnormality, such as:
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
Of course, you can throw more than one type Exception
, but a from the first catch
to the clause to handle
if catch
the type of clause is not specified, it can handle any type of exception:
try {
throw 'This a Exception!';
} on Exception catch(e) {
print('Unknown exception: $e');
} catch(e) {
print('Unknown type: $e');
}
Whether or not an exception occurs, if you want to execute a piece of code, you can finally
achieve:
try {
throw 'This a Exception!';
} catch(e) { // 如果去掉 catch 语句,那么异常将会在finally代码块之后传递。
print('Catch Exception: $e');
} finally {
print('Close');
}
Classes and Objects
Dart, all objects are instances of classes, and all classes are Object
subclasses.
Definitions and class constructor
Class definition with class
a keyword, if not explicitly defined constructor, an empty default constructor, which coincides with Java. In addition, Dart also provides named constructor of this function, the format is: Class.costructorName(var params)
. This usage is very practical in some scenarios, such as:
class Person{
String name;
int age;
bool sex;
String hobby;
Person(this.name, this.age, this.sex, this.hobby);
/// 命名构造函数
Person.fromJson(Map json){
print("Person constructor...");
this.name = json['name'];
this.age = json['age'];
this.sex = json['sex'];
this.hobby = json['hobby'];
}
}
By naming the constructor, I can be generated directly by the current class instance of a variety of ways, where Json format data generated by the Person
object. Further, if the constructor is simply passed parameters, can also be added directly after the constructor :
for parameterizing, by a plurality of parameters can be ,
linked:
class Point {
num x;
num y;
num z;
Point(this.x, this.y, z) { //第一个值传递给this.x,第二个值传递给this.y
this.z = z;
}
Point.fromeList(var list): //命名构造函数,格式为Class.name(var param)
x = list[0], y = list[1], z = list[2]{//使用冒号初始化变量
}
//当然,上面句你也可以简写为:
//Point.fromeList(var list): this(list[0], list[1], list[2]);
String toString() => 'x:$x y:$y z:$z';
}
If you want to create an immutable object, you can define compile-time constant objects
need to be added before the constructor const
:
class ImmutablePoint {
final num x;
final num y;
const ImmutablePoint(this.x, this.y); // 常量构造函数
static final ImmutablePoint origin = const ImmutablePoint(0, 0); // 创建一个常量对象不能用new,要用const
}
Property accessor
That is, we often say Setter/Getter
, it is mainly used to read and write a property method. Each field corresponds to an implicit Getter
and Setter
, when it is invoked obj.name
, instead obj.name()
. Of course, you can get
and set
keyword extensions
to achieve their own Setter/Getter
, if the field is final
or const
, then it can have only one getter
method. Such as:
class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// Define two calculated properties: right and bottom.
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
Plant constructors
Not any time, we need to create a new object, such as: a cache can return a good object or class has a subclass object. We return to the class of a cache object as an example:
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
return _cache.putIfAbsent(
name, () => Logger._internal(name));
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
Note: factory constructor can not
this
key to get the members of the class.
Abstract class
Dart and no interface
keywords, only abstract
to modify "abstract class", but here's an abstract class can either be inherited (the extends) , can also be achieved (the implements) . Such as:
abstract class Person { // 可以不用 abstract 修饰,如果加上 abstract 的话 Person 不能被实例化
String greet(who);
}
class Student implements Person {
String name;
Student(this.name);
String greet(who) => 'Student: I am $name!';
}
class Teacher implements Person {
String name;
Teacher(this.name);
String greet(who) => 'Teacher: I am $name!';
}
void main() {
Person student = new Student('Wang');
Person teacher = new Teacher('Lee');
print( student.greet('Chen'));
print(teacher.greet('Chen'));
}
Similarly, Dart is the class of single inheritance, implement . As used herein implements
, the subclass Student
unable to access the parent class Persion
of variables, but the abstract methods must be explicitly implemented. Conversely, if the extends
inherit, subclasses can be used as the parent class of non-private variable, if the parent class is not an abstract class, then the subclass does not need to explicitly implement inside the same method. Such as:
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(String who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Impostor implements Person {
get _name => '';
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
Operator overloading
The following operators support overloaded functions:
< |
+ |
| |
[] |
---|---|---|---|
> |
/ |
^ |
[]= |
<= |
~/ |
& |
~ |
>= |
* |
<< |
== |
– |
% |
>> |
This point kotlin language functions like operator overloading. We expressed the following plane vector class, for example, to add two vectors which addition and subtraction functions:
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
// Operator == and hashCode not shown. For details, see note below.
// ···
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
enumerate
Enumeration relatively simple to use, and the use of Java in the similar element declaration of index
value from the 0
calculation begins.
enum Color { red, green, blue }
......
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
Mixin Mixed Mode
Mixins a plurality of classes in the hierarchy in a manner multiplexed class code. After the class name to add with
keywords, and with
immediately after the list of identifiers classes , separated by commas, such as:
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
If you want to declare a mixed-mode, it can mixin
be replaced class
define a class constructor does not contain:
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
Of course, we can also specify a class to use mixed mode defined by on
keyword:
mixin MusicalPerformer on Musician {
// ···
}
Static variables and functions
Define static variables and functions similar to Java methods:
class Point {
num x, y;
Point(this.x, this.y);
static const originalPoint = Point(0, 0);
static num distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
// usage
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
Asynchronous operation
Dart is a single thread of execution, if the I / O operation or time-consuming operation, the program may block occur. Dart library functions return a lot Future
or Stream
objects, these methods are, they can be returned asynchronously executed after the establishment of a time-consuming operation, without waiting for the completion of the implementation of time-consuming operation.
We can achieve asynchronous operation in two ways:
- By
async
andawait
realization - Future API is implemented by means of
async 和 await
By async
and await
keywords, we can easily implement asynchronous operation. To use await
, you must use the function you want to async
modify, while the function returns an Future
object. Simple usage is as follows:
Future checkVersion() async {
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
}
Builder
Sync generator - Sync *
It is worth noting that the synchronous generator returns
Iterable
an object:Iterable<int> naturalsTo(int n) sync* { int k = 0; while (k < n) yield k++; }
Asynchronous generator - the async *
Asynchronous generator returned
Stream
objects:Stream<int> asynchronousNaturalsTo(int n) async* { int k = 0; while (k < n) yield k++; }
yield*
By
yield*
improved performance in the recursion:Iterable<int> naturalsDownFrom(int n) sync* { if (n > 0) { yield n; yield* naturalsDownFrom(n - 1); } }
The class object as a function call
Dart allows us to target a class as a function call , only need to implement the call()
function can be:
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = new WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out');
}
To be continued
This article is just a starting point Dart journey, is also a cornerstone of Flutter in the follow-up as well as more advanced usage details and API waiting for us to dig, keep learning!