flutter基础语法:类
1. 定义
Dart 是面向对象的编程语言,在 Dart 里一切都是对象,而每一个对象是某个类的实例。Dart 中用关键字class
标识类,例如:
class Point {
double? x; // Declare instance variable x, initially null.
double? y; // Declare y, initially null.
double z = 0; // Declare z, initially 0.
}
上面例子定义了类Point
,它包含三个实例变量x,y,z
,其中x,y
可以为空,z
不为空。对象通过.
操作符可以访问实例变量和方法,例如:
class Point {
double? x, y;
double z = 0;
Point(this.x, this.y);
double distance() {
return z * z + (y ?? 0.0) * (y ?? 0.0) + (x ?? 0.0) * (x ?? 0.0);
}
}
void main() {
var p = Point(3, 4);
print(p.x);
print(p.y);
p.z = 5;
print(p.distance());
}
所有的实例变量都会隐式的生成getter
方法,非final
或者late final
的实例变量会隐式的生成setter
方法。你可以通过set
和get
关键字,新增实例变量。例如:
class Point {
double? x, y;
double z = 0;
Point(this.x, this.y);
double get k => z + 1;
double distance() {
return z * z + (y ?? 0.0) * (y ?? 0.0) + (x ?? 0.0) * (x ?? 0.0);
}
}
void main() {
var p = Point(3, 4);
print(p.k);
}
2. 构造函数
构造函数用来构造一个类的对象,最常见的构造函数是:在类里定义一个和类名相同的方法。例如:
class Point {
double x = 0;
double y = 0;
Point(double x, double y) {
// See initializing formal parameters for a better way
// to initialize instance variables.
this.x = x;
this.y = y;
}
}
Dart 还提供下面方式的构造函数。
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);
}
如果类没有声明构造函数,Dart 会生成一个默认的构造函数,默认构造函数没有参数,会调用父类的无参构造函数。
2.1 命名构造函数
Dart 里构造函数的形式可以是 ClassName 和 ClassName.indentify,其中后者叫命名构造函数,例如:
class Point {
double x = 0, y = 0;
Point.fromJson(Map<String, double> map) {
x = map['x']!;
y = map['y']!;
}
double get len => x + y;
}
void main() {
var p = Point.fromJson({"x": 2.5, "y": 3.0});
print(p.len);
}
2.2 初始化列表
初始化列表允许在执行构造函数之前对变量进行初始化,例如:
class Point {
double x = 0, y = 0, z = 0;
Point.fromJson(Map<String, double> map)
: x = map['x']!,
y = map['y']! {
z = map['z']!;
}
double get len => x + y + z;
}
void main() {
var p = Point.fromJson({"x": 2.5, "y": 3.0, "z": 10});
print(p.len);
}
2.3 调用父类构造函数
构造函数的执行顺序如下:
- 初始化列表。
- 调用父类无参构造函数。
- 执行自己的构造函数。
如果父类没有无参构造函数,需要指定调用某个父类的构造函数,例如:
class Shape {
int width = 0, height = 0;
Shape(int width, int height) {
this.width = width;
this.height = height;
}
}
class Rectangle extends Shape {
int w1 = 0, w2 = 0;
Rectangle.fromJson(Map<String, int> map)
: w1 = map['w1']!,
super(map['width']!, map['height']!) {
w2 = map['w2']!;
}
}
void main() {
Rectangle a = Rectangle.fromJson({"width": 1, "height": 2, "w1": 3, "w2": 4});
print(a.width);
}
2.4 redirect构造函数
有些构造函数直接调用其他构造函数,这被称作 Redirecting constructors,例如:
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);
}
3. 方法
方法是为对象提供行为的函数,前面例子中的distance
便是方法。
3.1 操作符
操作符是特殊的方法,Dart 支持的操作符列表如下:
< | + | | | >>> |
---|---|---|---|
> | / | ^ | [] |
<= | ~/ | & | []= |
>= | * | << | ~ |
- | % | >> | == |
通过实现操作符来实现对象的加减乘除等。例如:
class A {
int x = 0, y = 0;
A(this.x, this.y);
A operator +(B b) => A(x + b.x, y + b.y);
}
class B {
int x = 0, y = 0;
B(this.x, this.y);
}
void main() {
A ret = A(2, 3) + B(3, 4);
print(ret.x);
}
操作符并不要求两个操作数类型一样(A+B
合法),因为 Dart 不支持重载( overloading ),所以没有办法定义多个相同的operator
。
4. 抽象类
Dart 使用关键字abstract
标识一个抽象类,抽象类无法被实例化。抽象类里往往会声明抽象方法,抽象方法只有方法的签名,没有实现。
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...
}
}
5. 接口
Dart 中没有 interface 这样的关键字来标识接口,在 Dart 中,每一个类都隐式的声明了一个接口,这个接口包含了所有的实例变量、方法等。implements
关键字表示实现接口,例如:
class A {
int a = 0;
int compute() => a * a;
}
class B implements A {
@override
int a = 0;
@override
int compute() {
// TODO: implement compute
throw UnimplementedError();
}
}
B
实现A
时,需要实现A
中定义的所有方法,包括setter
和getter
。
extends
和implements
两个关键字在继承抽象类时,行为有点类似,但是这两个关键字差别很大。
extends
表示继承某一个类,它拥有父类的所有实例变量和方法等。implements
表示实现某一个类,它只继承了类型,并且重新实现了父类的所有方法。