Dart 学习笔记-类、枚举、方法

参考:https://www.dartcn.com/guides/language/language-tour#%E7%B1%BB

Dart 是一种基于类和 mixin 继承机制的面向对象的语言。 每个对象都是一个类的实例,所有的类都继承于 Object

基于 Mixin 继承 意味着每个类(除 Object 外) 都只有一个超类, 一个类中的代码可以在其他多个继承类中重复使用。

使用类的成员变量

对象的由函数和数据(即方法和实例变量)组成。 方法的调用要通过对象来完成: 调用的方法可以访问其对象的其他函数和数据。

使用 (.) 来引用实例对象的变量和方法:

var p = Point(2, 2);

// 为实例的变量 y 设置值。
p.y = 3;

使用 ?. 来代替 . , 可以避免因为左边对象可能为 null , 导致的异常:

var p = Point(2, 2);

// 如果 p 为 non-null,设置它变量 y 的值为 4。
p?.y = 4;

使用构造函数

通过 构造函数 创建对象。 构造函数的名字可以是 ClassName 或者 ClassName.identifier。例如, 以下代码使用 PointPoint.fromJson() 构造函数创建 Point 对象:

var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});

获取对象的类型

使用对象的runtimeType 属性, 可以在运行时获取对象的类型, runtimeType 属性回返回一个 Type 对象。

print('The type of a is ${a.runtimeType}');

构造函数

通过创建一个与其类同名的函数来声明构造函数

class Point {
  num x, y;

  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}

通常模式下,会将构造函数传入的参数的值赋值给对应的实例变量, Dart 自身的语法糖精简了这些代码:

class Point {
  num x, y;

  // 在构造函数体执行前,
  // 语法糖已经设置了变量 x 和 y。
  Point(this.x, this.y);
}

在没有声明构造函数的情况下, Dart 会提供一个默认的构造函数。 默认构造函数没有参数并会调用父类的无参构造函数。

子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数 (匿名,没有参数) 。

重定向构造函数

有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。 重定向构造函数的函数体为空, 构造函数的调用在冒号(:)之后。(类似于Android中自定义 View需要实现多个构造函数时调用最终的构造函数)

class Point {
  num x, y;

  // 类的主构造函数。
  Point(this.x, this.y);

  // 指向主构造函数
  Point.alongXAxis(num x) : this(x, 0);
}

工厂构造函数

当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字。 例如,一个工厂构造函数可能会返回一个 cache 中的实例, 或者可能返回一个子类的实例。
(类似于Android中单例模式)

以下示例演示了从缓存中返回对象的工厂构造函数:

class Logger {
  final String name;
  bool mute = false;

  // 从命名的 _ 可以知,
  // _cache 是私有属性。
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}

提示: 工厂构造函数无法访问 this。

工厂构造函的调用方式与其他构造函数一样:

var logger = Logger('UI');
logger.log('Button clicked');

方法

方法是为对象提供行为的函数。

实例方法

对象的实例方法可以访问 this 和实例变量。 以下示例中的 distanceTo() 方法就是实例方法:

import 'dart:math';

class Point {
  num x, y;

  Point(this.x, this.y);

  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}

抽象方法

只定义接口不进行实现,而是留给其他类去实现。 抽象方法只存在于 抽象类 中。
定义一个抽象函数,使用分号(;)来代替函数体:

abstract class Doer {
  // 定义实例变量和方法 ...
  void doSomething(); // 定义一个抽象方法。
}

class EffectiveDoer extends Doer {
	@override
  void doSomething() {
    print("123");
    // 提供方法实现,所以这里的方法就不是抽象方法了...
  }
}

void main() {
  var eff = EffectiveDoer();
  eff.doSomething();
}

输出:
123

枚举类型

枚举类型也称为enumerations 或 enums , 是一种特殊的类,用于表示数量固定的常量值。
使用 enum关键字定义一个枚举类型:

enum Color { red, green, blue }

枚举中的每个值都有一个index getter 方法, 该方法返回值所在枚举类型定义中的位置(从 0 开始)。
例如,第一个枚举值的索引是 0 , 第二个枚举值的索引是 1。

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);

使用枚举的values常量, 获取所有枚举值列表(list )。

List<Color> colors = Color.values;
assert(colors[2] == Color.blue);

为类添加功能: Mixin

Mixin 是复用类代码的一种途径, 复用的类可以在不同层级,之间可以不存在继承关系。

通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个Mixin 。 如果 Mixin不希望作为常规类被使用,使用关键字 mixin 替换 class 。 例如:

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');
    }
  }
}

通过 with 后面跟一个或多个混入的名称,来 使用 Mixin , 下面的示例演示了两个使用 Mixin 的类:

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    // Musical 类中的变量
    canConduct = true;
  }
}

指定只有某些类型可以使用的 Mixin -比如, Mixin 可以调用 Mixin 自身没有定义的方法 - 使用 on 来指定可以使用Mixin的父类类型:

mixin MusicalPerformer on Musician {
  // ···
}

mixin 详解可查看 Dart之Mixin详解

类变量和方法

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

静态变量

Dart中静态变量只到它们被使用的时候才会初始化。

Java中静态变量是随着类的加载而加载的,所以当类加载进内存的时候,静态变量就已经伴随着类的加载而初始化进内存了,并且静态变量只在类加载时加载一次,存放在方法区中的静态区中。

class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);
}

静态方法

静态方法(类方法)不能在实例上使用,因此它们不能访问 this 。 例如:

import 'dart:math';

class Point {
  num x, y;
  Point(this.x, this.y);

  static num 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);
}

输出:
2.8284271247461903
发布了180 篇原创文章 · 获赞 76 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/ITxiaodong/article/details/104154133