一、使用类成员
Use ?. instead of . to avoid an exception when the leftmost operand is null:
当最左边的操作符为空的时候,使用?避免异常
二、使用构造函数
You can create an object using a constructor. Constructor names can be either ClassName or ClassName.identifier.
使用构造器可以创建对象,构造器的名称可以是ClassName 或者 ClassName.identifier
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
Some classes provide constant constructors. To create a compile-time constant using a constant constructor, put the const keyword before the constructor name:
var p = const ImmutablePoint(2, 2);
If a constant constructor is outside of a constant context and is invoked without const, it creates a non-constant object:
在常量环境以外调用常量构造函数,创建的是非常量对象。
三、获取对象的类型
To get an object's type at runtime, you can use the Object property runtimeType, which returns a Type object.
print('The type of a is ${a.runtimeType}');
四、实例变量
All uninitialized instance variables have the value null.
没有初始化的实例变量的值是null
All instance variables generate an implicit getter method. Non-final instance variables and late final instance variables without initializers also generate an implicit setter method. For details, see Getters and setters.
实例变量产生隐式的get方法,非final变量和late final变量会产生set方法。
五、构造函数
Instance variables can be final, in which case they must be set exactly once. Initialize final, non-late instance variables at declaration, using a constructor parameter, or using a constructor's initializer list:
final类型的变量可以使用构成参数、初始化列表初始化
class Point {
final double x;
final double y;
// Sets the x and y instance variables
// before the constructor body runs.
Point(this.x, this.y);
}
六、默认构造函数
If you don’t declare a constructor, a default constructor is provided for you. The default constructor has no arguments and invokes the no-argument constructor in the superclass.
默认构造函数没有参数,并调用父类的无参构造函数
七、构造函数不能继承
Subclasses don’t inherit constructors from their superclass. A subclass that declares no constructors has only the default (no argument, no name) constructor. 子类不能继承构造函数,如果一个子类没有构造函数,那么只有默认构造函数
八、构造流程
- initializer list
- superclass's no-arg constructor
- main class's no-arg constructor
class Person {
String? firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson().
Employee.fromJson(super.data) : super.fromJson() {
print('in Employee');
}
}
Arguments to the superclass constructor don't have access to this. For example, arguments can call static methods but not instance methods.
九、初始化列表
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, double> json)
: x = json['x']!,
y = json['y']! {
print('In Point.fromJson(): ($x, $y)');
}
十、重定向构造函数
Sometimes a constructor’s only purpose is to redirect to another constructor in the same class. A redirecting constructor’s body is empty, with the constructor call (using this instead of the class name) appearing after a colon (:).
class Point {
double x, y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(double x) : this(x, 0);
}
十一、常量构造函数
If your class produces objects that never change, you can make these objects compile-time constants. To do this, define a const constructor and make sure that all instance variables are final.
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0);
final double x, y;
const ImmutablePoint(this.x, this.y);
}
十二、方法定义
class Point {
final double x;
final double y;
Point(this.x, this.y);
double distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
}
十三、运算符重载
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);
@override
bool operator ==(Object other) =>
other is Vector && x == other.x && y == other.y;
@override
int get hashCode => Object.hash(x, y);
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
十四、Getters 和setters
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);
@override
bool operator ==(Object other) =>
other is Vector && x == other.x && y == other.y;
@override
int get hashCode => Object.hash(x, y);
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
十五、抽象方法
Instance, getter, and setter methods can be abstract, defining an interface but leaving its implementation up to other classes. Abstract methods can only exist in abstract classes.
定义接口,实现在其他类中的方法是抽象方法。抽象方法只能定义在抽象类中。
To make a method abstract, use a semicolon (;) instead of a method body:
abstract class Doer {
// Define instance variables and methods...
void doSomething(); // Define an abstract method.
}
class EffectiveDoer extends Doer {
void doSomething() {
// Provide an implementation, so the method is not abstract here...
}
}
十六、抽象类
Use the abstract modifier to define an abstract class—a class that can’t be instantiated. Abstract classes are useful for defining interfaces, often with some implementation. If you want your abstract class to appear to be instantiable, define a factory constructor.
使用abstract定义的抽象类,不能被实例化。抽象类有用的地方是定义接口。
Abstract classes often have abstract methods. Here’s an example of declaring an abstract class that has an abstract method:
// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer {
// Define constructors, fields, methods...
void updateChildren(); // Abstract method.
}
十六、隐式接口
Every class implicitly defines an interface containing all the instance members of the class and of any interfaces it implements. If you want to create a class A that supports class B’s API without inheriting B’s implementation, class A should implement the B interface.
A class implements one or more interfaces by declaring them in an implements clause and then providing the APIs required by the interfaces. For example:
说白了, implements关键字 只能继承定义,不能继承实现。
十七、继承
Use extends to create a subclass, and super to refer to the superclass:
十八、noSuchMethod
You can't invoke an unimplemented method unless one of the following is true:
- The receiver has the static type
dynamic. - The receiver has a static type that defines the unimplemented method (abstract is OK), and the dynamic type of the receiver has an implementation of
noSuchMethod()that's different from the one in classObject.