成员访问
使用.访问类的对象成员,使用?.访问可能为空的类对象的成员
var p = Point(2, 2);
int x = p.x;
Point? q;
int y = q?.y
构造函数
构造函数的命名遵循ClassName
或者ClassName.identifier
,例如:
class Person {
const Person();
Person.fromJson();
}
一些类会提供常量const的构造函数,要使用常量const的构造函数,在调用类的构造函数前添加const 关键字,例如:
const p = const Person();
构造函数是不会被子类继承的
类的构造函数可以重定向到类的另外一个构造函数,例如
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);
}
工厂构造函数
使用factory 关键字定义工厂构造函数,工厂构造函数并不一定会创建新的类,可以用工厂构造函数实现单例类,方法如下:
class Singleton {
// step 1: 构造函数私有
Singleton._internal();
// step 2: 定义单例对象
static final Singleton _instance = Singleton._internal();
// step 3: // 用工厂函数返回单例对象
factory Singleton() => _instance;
}
超类初始化参数列表,用法如下:
class Vector2d {
final double x;
final double y;
Vector2d(this.x, this.y);
}
class Vector3d extends Vector2d {
final double z;
// Forward the x and y parameters to the default super constructor like:
// Vector3d(final double x, final double y, this.z) : super(x, y);
Vector3d(super.x, super.y, this.z);
}
成员函数
操作符重写例子:
@override
bool operator ==(Object other) =>
other is Vector && x == other.x && y == other.y;
Getters和Setters例子
class Person {
String _name;
String get name => _name;
set name(String s) => _name = s;
}
抽象方法
抽象方法只能存在于抽象类或者混入(mixins), 抽象方法的定义方式,只需要声明函数原先即可
abstract class Base {
void show(); // 定义抽象方法
}
混入
Mixin 是一种定义可在多个类层次结构中重用的代码的方法。要使用 mixin,请使用with
关键字后跟一个或多个 mixin 名称。以下示例显示了两个使用 mixin 的类:
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
要定义 mixin,请使用mixin
声明。在极少数情况下,您需要同时定义 mixin和类,您可以使用mixin class
声明。
Mixins 和 mixin 类不能有extends
子句,并且不能声明任何生成构造函数。例如:
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');
}
}
}
扩展
扩展用于给库添加函数,你可以在不知道库细节的情况下扩展库中某些类的方法,例如下面的代码把string转化为int
int.parse('42')
可以用扩展实现为更简单的语法
'42'.parseInt()
要启用该代码,您需要导入包含该类扩展的库String
:
import 'string_apis.dart';
// ···
print('42'.parseInt()); // Use an extension method.
扩展的实现
使用以下语法创建扩展:
extension <extension name>? on <type> {
(<member definition>)*
}
扩展String 实现parseInt方法,代码如下
// string_api.dart
extension NumberParsing on String {
int parseInt() {
return int.parse(this);
}
double parseDouble() {
return double.parse(this);
}
}
接口
每个dart类默认定义了一个隐含接口,接口包括类的所有实例成员,如果想要创建一个类实现另外一个类的所有接口,而又不想继承这个类,可以用实现接口的方式,例如:
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final String _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 {
String 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()));
}
可调用对象
实现call()方法,可以让Dart类实例像函数一样调用,例如:
class WannabeFunction {
String call(String a, String b, String c) => '$a $b $c!';
}
var wf = WannabeFunction();
var out = wf('Hi', 'there,', 'gang');
void main() => print(out);