0°

Dart入门—类与方法

Dart入门—类与方法

实例变量

声明实例变量时,所有未初始化的实例变量的值为null


1
2
3
4
5
6
7
8
9
10
11
12
13
1void main(){
2    var point = new Point();
3    point.x = 4;
4    print(point.x);
5    print(point.y);
6}
7
8class Point {
9    int x;      // null
10    int y;      // null
11    int z = 0;  // 0
12}
13

构造函数

声明构造函数

如果你没有声明构造函数,默认有构造函数,默认构造函数没有参数,调用父类的无参构造函数。子类不能继承父类的构造函数

构造函数就是一个与类同名的函数,关键字 this 是指当前的,只有在命名冲突时有效,否则dart会忽略处理


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1void main(){
2    var point = new Point(4, 5);
3}
4
5class Point {
6    int x;
7    int y;
8
9    Point(int x, int y) {
10        this.x = x;
11        this.y = y;
12    }
13}
14

一个实例变量分配一个构造函数参数会使语法更简单


1
2
3
4
5
6
7
8
9
10
11
1void main(){
2    var point = new Point(1, 3);
3}
4
5class Point {
6    int x;
7    int y;
8
9    Point(this.x, this.y);
10}
11

命名构造函数

使用命名构造函数让类有多个构造函数


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1void main(){
2    var point = new Point.fromJson({'x':2, 'y':4});
3}
4
5class Point {
6    int x;
7    int y;
8
9    Point(this.x, this.y);
10
11    // 命名构造函数
12    Point.fromJson(Map json) {
13        x = json['x'];
14        y = json['y'];
15    }
16}
17

父类的构造函数

子类构造函数调用父类的默认构造函数,如果父类没有默认构造函数,必须手动调用父类的构造函数,在 : 号后面指定父类的构造函数


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1void main(){
2    var emp = new Employee.fromJson({});
3}
4
5class Person {
6    Person.fromJson(Map data) {
7        print("in Person");
8    }
9}
10
11class Employee extends Person {
12    Employee.fromJson(Map data) : super.fromJson(data) {
13        print("in Employye");
14    }
15}
16

初始化实例变量

除了调用父类的构造函数,还可以在构造函数体运行之前初始化实例变量


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1void main(){
2    var emp = new Point.fromJson({'x':5, 'y':6});
3}
4
5class Point {
6    int x;
7    int y;
8
9    Point(this.x, this.y);
10
11    Point.fromJson(Map jsonMap): x = jsonMap['x'], y = jsonMap['y'] {
12        print("In Point.fromJson(): ($x, $y)");
13    }
14}
15

重定向构造函数

构造函数可以重定向到同类的另一个构造函数


1
2
3
4
5
6
7
8
9
10
11
12
13
1void main(){
2    var emp = new Point.alongXAxis(7);
3}
4
5class Point {
6    int x;
7    int y;
8
9    Point(this.x, this.y);
10
11    Point.alongXAxis(int x): this(x, 0);
12}
13

常量构造函数

想让类生成的对象永远不会改变,可以让这些对象变成编译时常量,定义一个const构造函数并确保所有实例变量是final的


1
2
3
4
5
6
7
8
9
10
11
1void main(){
2    var emp = new ImmutablePoint(7, 8);
3}
4
5class ImmutablePoint {
6    final int x;
7    final int y;
8    const ImmutablePoint(this.x, this.y);
9    static final ImmutablePoint origin = const ImmutablePoint(0, 0);
10}
11

工厂构造函数

使用factory关键字实现构造函数时,不一定要创建一个类的新实例,例如,一个工厂的构造函数可能从缓存中返回一个实例,或者返回一个子类的实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1void main(){
2    var logger = new Logger("UI");
3    logger.log("Button clicked");
4}
5
6class Logger {
7    final String name;
8    bool mute = false;
9
10    static final Map<String, Logger> _cache = <String, Logger>{};
11
12    factory Logger(String name) {
13        if (_cache.containsKey(name)) {
14            return _cache[name];
15        } else {
16            final logger = new Logger._internal(name);
17            _cache[name] = logger;
18            return logger;
19        }
20    }
21
22    Logger._internal(this.name);
23
24    void log(String msg) {
25        if (!mute) {
26            print(msg);
27        }
28    }
29}
30

实例方法

实例对象可以访问实例变量和方法


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1import "dart:math";
2
3void main(){
4    var point = new Point(12, 24);
5}
6
7class Point {
8    int x;
9    int y;
10    Point(this.x, this.y);
11
12    int distanceTo(Point other) {
13        int dx = x - other.x;
14        int dy = y - other.y;
15        return sqrt(dx * dx + dy * dy);
16    }
17}
18

getter和setter

getter和setter是特殊的方法,可以读写访问对象的属性,每个实例变量都有一个隐式的getter,适当的加上一个setter,可以通过实现getter和setter创建附加属性,使用get和set关键词


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1void main(){
2    var rect = new Rectangle(3, 4, 20, 15);
3    print(rect.left);
4    rect.right = 12;
5    print(rect.left);
6}
7
8class Rectangle {
9    int left;
10    int top;
11    int width;
12    int height;
13
14    Rectangle(this.left, this.top, this.width, this.height);
15
16    int get right => left + width;
17        set right(int value) => left = value - width;
18    int get botton => top + height;
19        set botton(int value) => top = value - height;
20}
21

抽象方法

实例、getter和setter方法可以是抽象的,抽象方法使用分号 ; 而不是方法体


1
2
3
4
5
6
7
8
9
10
11
12
13
1abstract class Doer {
2    //...定义实例变量和方法...
3
4    //定义一个抽象方法
5    void doSomething();
6}
7
8class EffectiveDoer extends Doer {
9    void doSomething() {
10      //...实现一个抽象方法...
11    }
12}
13

重写运算符

您可以覆盖的运算符:<、+、|、[]、>、/、^、[]=、<= 、/、&、、>=、*、<<、==、– 、%、>>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1void main(){
2    final v = new Vector(2, 3);
3    final w = new Vector(2, 2);
4
5    print(v.x == 2 &amp;&amp; v.y == 3);
6    print((v + w).x == 4 &amp;&amp; (v + w).y == 5);
7    print((v - w).x == 0 &amp;&amp; (v - w).y == 1);
8}
9
10class Vector {
11    final int x;
12    final int y;
13    const Vector(this.x, this.y);
14
15    // 重写 + (a+b)
16    Vector operator +(Vector v) {
17        return new Vector(x + v.x, y + v.y);
18    }
19
20    // 重写 - (a-b)
21    Vector operator -(Vector v) {
22        return new Vector(x - v.x, y - v.y);
23    }
24}
25

抽象类

使用abstract修饰符定义的抽象类不能被实例化,抽象类用于定义接口,常用于实现,抽象类里通常有抽象方法,有抽象方法的不一定是抽象类


1
2
3
4
5
6
7
1abstract class AbstractContainer {
2  //...定义构造函数,字段、方法...
3
4  //抽象方法
5  void updateChildren();
6}
7

隐式接口

每个类都有一个隐式定义的接口,包含所有类和实例成员,通过implements子句声明一个类实现一个或多个接口,然后提供所需的api接口


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1void main(){
2    print(greetBob(new Person(&quot;kathy&quot;)));
3    print(greetBob(new Imposter()));
4}
5
6class Person {
7    final _name;
8    Person(this._name);
9    String greet(who) =&gt; &quot;Hello, $who. I am $_name.&quot;;
10}
11
12class Imposter implements Person {
13    final name = &quot;&quot;;
14    String greet(who) =&gt; &quot;Hi $who. Do you know who I am?&quot;;
15}
16
17greetBob(Person person) =&gt; person.greet(&quot;bob&quot;);
18

实现多个接口


1
2
3
4
1class Point implements Comparable, Location {
2    // ...
3}
4

类的继承

使用extends创建子类,super引用父类,子类可以重写实例方法、getter和setter,使用@override注释重写,使用@proxy注释来忽略警告


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1class Television {
2    void turnOn() {
3        _illuminateDisplay();
4        _activateIrSensor();
5    }
6}
7
8class SmartTelevision extends Television {
9    void turnOn();
10    _bootNetworkInterface();
11    _initializeMemory();
12    _upgradeApps();
13}
14

枚举类型

枚举类型是一种特殊的类,用于表示一个固定数量的常量值,不能实例化,使用enum关键字声明一个枚举类型


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1void main(){
2    print(Color.red.index);     // 0
3    print(Color.green.index);   // 1
4    print(Color.blue.index);    // 2
5
6    // 获得枚举值的列表
7    List&lt;Color&gt; colore = Color.values;
8    print(colore[2]);   // Color.blue
9
10    // 在switch语句中使用枚举
11    Color aColor = Color.blue;
12    switch(aColor) {
13        case Color.red:
14            print(&quot;Red as Roses!&quot;);
15            break;
16        case Color.green:
17            print(&quot;Green as grass!&quot;);
18            break;
19        default:
20            print(aColor);
21    }
22}
23
24enum Color {
25    red,
26    green,
27    blue
28}
29

扩展类

使用with关键字后面跟着一个或多个扩展类名


1
2
3
4
5
6
7
8
9
10
11
1class Musician extends Performer with Mnsical {
2    // ...
3}
4
5class Maestro extends Person with Musical, Aggressive, Demented {
6    Maestro(String maestroName) {
7        name = maestroName;
8        canConduct = true;
9    }
10}
11

要实现扩展类,创建一个没有构造函数,没有父类调用的类


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1abstract class Musical {
2    bool canPlayPiano = false;
3    bool canCompose = false;
4    bool canConduct = false;
5
6    void entertainMe() {
7        if (canPlayPiano) {
8            print(&#x27;Playing piano&#x27;);
9        } else if (canConduct) {
10            print(&#x27;Waving hands&#x27;);
11        } else {
12            print(&#x27;Humming to self&#x27;);
13        }
14    }
15}
16

类的变量和方法

使用static关键字实现类的变量和方法

静态变量

静态变量即类变量,是类的常量


1
2
3
4
5
6
7
8
9
10
11
12
13
1void main(){
2    print(Color.red.name);  // red
3}
4
5class Color {
6    // 静态常量
7    static const red = const Color(&quot;red&quot;);
8    // 不可变的实例变量
9    final String name;
10    // 构造常量函数
11    const Color(this.name);
12}
13

静态方法

静态方法即类方法,没有实例,因此无法通过实例访问


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1import &quot;dart:math&quot;;
2
3void main(){
4    var a = new Point(2, 2);
5    var b = new Point(4, 4);
6    var distance = Point.distanceBetween(a, b);
7    print(distance);    // 2.8284271247461903
8}
9
10class Point {
11    int x;
12    int y;
13    Point(this.x, this.y);
14
15    static int distanceBetween(Point a, Point b) {
16        var dx = a.x - b.x;
17        var dy = a.y - b.y;
18        return sqrt(dx * dx + dy * dy);
19    }
20}
21
「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!