以下内容来自Flutter官方的“为Java开发人员准备的Dart教程”中记录的笔记。
一、创建一个简单地Dart类
定义Bicycle类
class Bicycle {
int cadence;
int speed;
int gear;
}
void main() {
}
- 如果在
main()
方法中需要访问命令行传过来的参数,可以使用main(List<String> args)
方法。 - 在Dart中可以在类之外编写代码、变量、方法、存取方法。
main()
还是Bicycle类都默认是public的,Dart中没有public、private、protected等关键字。
定义一个Bicycle的构造函数
在Bicycle类中增加以下的构造函数:
Bicycle(this.cadence, this.speed, this.gear);
- 在Dart中构造函数没有方法体是合法的。
- 构造函数参数中使用this,可以直接对实例变量进行赋值,不用编写多与代码。
- 上述代码与下列的代码功效相同。
Bicycle(int cadence, int speed, int gear) {
this.cadence = cadence;
this.speed = speed;
this.gear = gear;
}
优化输出信息
所有的Dart类中都有一个toString()
方法,可以直接复写这个方法来提供更具体的输出信息。
@override
String toString() => 'Bicycle: $speed mph';
- 可以在字符串中使用
${expression}
方法来实现字符串模板的效果,如果该表达式仅是一个标识符,可以去掉花括号$variableName
。 - 只有一行的方法可以使用
=>
来简写。
增加只读变量
可以在变量名前新增下划线_
来标记它是私有的,就是说可以仅通过改变变量名来实现将变量标记为只读。
int _speed = 0;
在Bicycle类中增加getter方法
int _speed = 0;
int get speed => _speed;
- 未初始化的变量(即使是数字类型)的值都是null。
- 默认情况下,Dart 会为所有公开的变量提供存取方法,除非你需要提供仅仅可读、可写,或者在某些情况下需要在 getter 方法中进行计算或是在 setter 方法中进行某些值得更新,否则都不需要再重新定义存取方法。
- 在之前 Java 例子中,cadence 和 gear 都有自己的存取方法,而在此例子中,这些实例变量可以直接通过 bike.gear 或者 bike.cadence 访问到。
二、使用可选参数(而不是使用重载)
import 'dart:math';
class Rectangle {
int width;
int height;
Point origin;
}
添加Rectangle构造方法
Rectangle({this.origin = const Point(0, 0), this.width = 0, this.height = 0});
this.origin
,this.width
和this.height
使用了 Dart 提供的简便方法来直接对类中的实例变量进行赋值。this.origin
,this.width
和this.height
嵌套在闭合的花括号中 ({}
) ,用来表示它们是可选的命名参数。this.origin = const Point(0, 0)
这样的代码表明给实例变量origin
提供了默认的值Point(0,0)
,默认值必须是在编译期就可以确定的常量。上述代码中的构造方法为三个实例变量都提供了默认参数。
使用构造方法
main() {
print(Rectangle(origin: const Point(10, 20), width: 100, height: 200));
print(Rectangle(origin: const Point(10, 10)));
print(Rectangle(width: 200));
print(Rectangle());
}
三、创建工厂模式
在 Java 中工厂类是一个广泛使用的设计模式,它相比较直接对类进行实例化来说,具有诸多优势,比如隐藏实例化的具体细节,提供可以配置为其他类的能力,直接返回一个已有的对象而不是直接返回一个新的对象。
在该步骤中,将展示两种实现一个创建Shape的工厂类的方法。
- 选项 1:创建一个顶层的方法
- 选项2 :创建一个工厂模式的构造方法
在这个练习中,你将会使用一个 Shapes 实例来实例化形状的类,并输出打印出他们的面积:
import 'dart:math';
abstract class Shape {
num get area;
}
class Circle implements Shape {
final num radius;
Circle(this.radius);
num get area => pi * pow(radius, 2);
}
class Square implements Shape {
final num side;
Square(this.side);
num get area => pow(side, 2);
}
main() {
final circle = Circle(2);
final square = Square(2);
print(circle.area);
print(square.area);
}
- Dart支持抽象类。
- 一个文本中可以定义多个类。
选项1:创建一个顶层的方法
Shape shapeFactory(String type) {
if (type == 'circle') return Circle(2);
if (type == 'square') return Square(2);
throw 'Can\'t create $type.';
}
替换main()
方法中前两行代码
final circle = shapeFactory('circle');
final square = shapeFactory('square');
选项2:创建一个工厂模式的构造方法
使用 Dart 的 factory
关键字来创建一个工厂模式的构造方法
// 在抽象类 Shape 中增加一个工厂模式的构造方法
abstract class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle(2);
if (type == 'square') return Square(2);
throw 'Can\'t create $type.';
}
num get area;
}
替换main()方法中前两行
final circle = Shape('circle');
final square = Shape('square');
四、接口实现
Dart并没有提供 interface
关键字,但是每一个类都隐式地定义了一个接口。
扩展Circle类,增加一个CircleMock:
class CircleMock implements Circle {}
// 上述代码会看到一个 Missing concrete implementations 的错误
// 添加两个实例变量 area 和 radius 即可修复这个问题
class CircleMock implements Circle {
num area;
num radius;
}
- 虽然 CircleMock 并没有定义任何行为,但是在 Dart 中这是完全合法的,不会有任何报错。