- 基于 mixin 的继承
- 根类是 Object
使用类成员
- 数据
- 函数
var p = Point(2, 2);
// Set the value of the instance variable y.
p.y = 3;
// Get the value of y.
assert(p.y == 3);
// Invoke distanceTo() on p.
double distance = p.distanceTo(Point(4, 4));
?.
避免对象为 null
// If p is non-null, set its y value to 4.
p?.y = 4;
使用构造函数
构造函数可以是:
- ClassName
- ClassName.identifier
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
- new 关键字是可选的
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
- 常量构造函数
var p = const ImmutablePoint(2, 2);
- 创建两次常量对象, 它们是相同的对象
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!
- 不用写过多 const 关键字
// 声明出所有 const
// Lots of const keywords here.
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
// Only one const, which establishes the constant context.
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
获取对象类型
- 返回类型对象
- 运行时类型 runtimeType
print('The type of a is ${a.runtimeType}');
实例变量
- 每个实例变量隐含实现 getter 方法
- 每个非 finall 实例变量隐含实现 setter 方法
class Point {
double x; // Declare instance variable x, initially null.
double y; // Declare y, initially null.
double z = 0; // Declare z, initially 0.
}
class Point {
double x;
double y;
}
void main() {
var point = Point();
point.x = 4; // Use the setter method for x.
assert(point.x == 4); // Use the getter method for x.
assert(point.y == null); // Values default to null.
}
构造函数
- 与类名相同
- 命名构造函数
- this
class Point {
double x, y;
Point(double x, double y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
- 给实例变量赋值的语法糖
class Point {
double x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
默认构造函数
如果没声明构造函数, dart 将会创建一个没有参数的构造函数, 并且调用父类的无参构造函数.
构造函数不会继承
没声明构造函数的子类只有默认的无参构造函数.
命名构造函数
- 实现多个构造函数
class Point {
double x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
调用非默认超类构造函数
- 默认情况下, 子类构造函数会调用父类非命名无参构造函数, 调用位置是子类构造函数体的开始.
各构造函数执行顺序:
- 初始化列表
- 父类无参构造函数
- 子类无参构造函数
- 如果父类没有未命名的无参构造函数, 那么需要使用
:
符号来明确调用父类的一个构造函数 :
是初始化列表, 就是在子类没有创建之前, 使用初始化列表来初始化父类, 有了父类才能有子类
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(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
// Prints:
// in Person
// in Employee
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
初始化列表
:
- 使用
,
分隔 - 不能使用
this
// 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)');
}
- 在开发模型下, 用于验证参数
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
- 初始化 final 字段
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
重定向构造函数
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);
}
常量构造函数
- 只要确保所有字段是 final 的
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final double x, y;
const ImmutablePoint(this.x, this.y);
}
工厂构造函数
- factory 关键字
- 可能不会创建新实例, 会从缓存中取出实例
- factory 无法访问 this
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));
}
factory Logger.fromJson(Map<String, Object> json) {
return Logger(json['name'].toString());
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
// 与普通构造函数使用方法相同
var logger = Logger('UI');
logger.log('Button clicked');
var logMap = {'name': 'UI'};
var loggerJson = Logger.fromJson(logMap);
方法
实例方法
import 'dart:math';
class Point {
double x, 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);
}
}
Getters 和 Setters
class Rectangle {
double left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// Define two calculated properties: right and bottom.
double get right => left + width;
set right(double value) => left = value - width;
double get bottom => top + height;
set bottom(double value) => top = value - height;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
抽象方法
- 抽象方法必须在抽象类中
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...
}
}
抽象类
// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer {
// Define constructors, fields, methods...
void updateChildren(); // Abstract method.
}
隐式接口
- 每个类隐式创建接口
// 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()));
}
- 实现多个接口
class Point implements Comparable, Location {...}
扩展类
- extends: 创建子类
- super: 引用父类
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
// ···
}
class SmartTelevision extends Television {
void turnOn() {
super.turnOn();
_bootNetworkInterface();
_initializeMemory();
_upgradeApps();
}
// ···
}
重载成员
@override
class SmartTelevision extends Television {
@override
void turnOn() {...}
// ···
}
可重载的操作符
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));
}
- 重写
==
时, 要求同时重写对象的hashCode
noSuchMethod()
- 在使用不存在的方法或实例变量时作出反应, 可以实现 noSuchMethod()
class A {
// Unless you override noSuchMethod, using a
// non-existent member results in a NoSuchMethodError.
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
扩展方法
import 'string_apis.dart';
...
print('42'.padLeft(5)); // Use a String method.
print('42'.parseInt()); // Use an extension method.
枚举类型
使用枚举
- 声明
enum Color { red, green, blue }
- 每个枚举值有一个
index
属性
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
- 获取枚举类型的所有值
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
- 在 switch 中使用枚举
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
Mixins
多重继承.
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
- mixins 类
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');
}
}
}
- 指定该 mixins 只能用在某类
mixin MusicalPerformer on Musician {
// ···
}
类变量和类方法
- static
静态变量
class Queue {
static const initialCapacity = 16;
// ···
}
void main() {
assert(Queue.initialCapacity == 16);
}
静态方法
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
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);
}