天天看点

Flutter之Dart语言(二)

接上篇文章继续记录有关Dart语言的基础。

目录

Classes

Constructors

Default constructors(默认构造函数)

Constructors aren’t inherited(构造函数不会继承)

Named constructors(命名构造函数)

Invoking a non-default superclass constructor(调用超类构造函数)

Initializer list(初始化列表)

Redirecting constructors(重定向构造函数)

Constant constructors(常量构造函数)

Factory constructors(工厂方法构造函数)

Methods(函数)

Instance methods(实例函数)

Getters and setters

Abstract methods(抽象函数)

Abstract classes(抽象类)

Implicit interfaces(隐式接口)

Enumerated types(枚举类型)

Adding features to a class: mixins(多重继承)

Class variables and methods(类变量和函数)

Generics(泛型)

Using parameterized types with constructors(在构造函数中使用泛型

Libraries and visibility

Using libraries(使用库)

Specifying a library prefix(指定库前缀)

Importing only part of a library(导入库的一部分)

Classes

Dart 是一个面向对象编程语言,同时支持基于 mixin 的继承机制。 每个对象都是一个类的实例,所有的类都继承于 Object.。 基于 Mixin 的继承 意味着每个类(Object 除外) 都只有一个超类,一个类的代码可以在其他 多个类继承中重复使用。

使用 

new

 关键字和构造函数来创建新的对象。 构造函数名字可以为 

ClassName

 或者 

ClassName.identifier

。例如:

var jsonData = JSON.decode('{"x":1, "y":2}');

// Create a Point using Point().
var p1 = new Point(2, 2);

// Create a Point using Point.fromJson().
var p2 = new Point.fromJson(jsonData);
           

Constructors

定义一个和类名字一样的方法就定义了一个构造函数 还可以带有其他可选的标识符,详情参考 Named constructors)(命名构造函数)。 常见的构造函数生成一个 对象的新实例:

class Point {
  num x;
  num y;

  Point(num x, num y) {
    // There's a better way to do this, stay tuned.
    this.x = x;
    this.y = y;
  }
}
           

由于把构造函数参数赋值给实例变量的场景太常见了, Dart 提供了一个语法糖来简化这个操作:

class Point {
  num x;
  num y;

  // Syntactic sugar for setting x and y
  // before the constructor body runs.
  Point(this.x, this.y);
}
           

Default constructors(默认构造函数)

如果你没有定义构造函数,则会有个默认构造函数。 默认构造函数没有参数,并且会调用超类的 没有参数的构造函数。

Constructors aren’t inherited(构造函数不会继承)

子类不会继承超类的构造函数。 子类如果没有定义构造函数,则只有一个默认构造函数 (没有名字没有参数)。

Named constructors(命名构造函数)

使用命名构造函数可以为一个类实现多个构造函数, 或者使用命名构造函数来更清晰的表明你的意图:

class Point {
  num x;
  num y;

  Point(this.x, this.y);

  // Named constructor
  Point.fromJson(Map json) {
    x = json['x'];
    y = json['y'];
  }
}
           

Invoking a non-default superclass constructor(调用超类构造函数)

默认情况下,子类的构造函数会自动调用超类的 无名无参数的默认构造函数。 超类的构造函数在子类构造函数体开始执行的位置调用。 如果提供了一个 initializer list(初始化参数列表) ,则初始化参数列表在超类构造函数执行之前执行。 下面是构造函数执行顺序:

  1. initializer list(初始化参数列表)
  2. superclass’s no-arg constructor(超类的无名构造函数)
  3. main class’s no-arg constructor(主类的无名构造函数)

如果超类没有无名无参数构造函数, 则你需要手工的调用超类的其他构造函数。 在构造函数参数后使用冒号 (

:

) 可以调用 超类构造函数。

Initializer list(初始化列表)

在构造函数体执行之前除了可以调用超类构造函数之外,还可以 初始化实例参数。 使用逗号分隔初始化表达式。

class Point {
  num x;
  num y;

  Point(this.x, this.y);

  // Initializer list sets instance variables before
  // the constructor body runs.
  Point.fromJson(Map jsonMap)
      : x = jsonMap['x'],
        y = jsonMap['y'] {
    print('In Point.fromJson(): ($x, $y)');
  }
}
           

Redirecting constructors(重定向构造函数)

有时候一个构造函数会调动类中的其他构造函数。 一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号调用其他构造函数。

class Point {
  num x;
  num y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}
           

Constant constructors(常量构造函数)

如果你的类提供一个状态不变的对象,你可以把这些对象 定义为编译时常量。要实现这个功能,需要定义一个 

const

 构造函数, 并且声明所有类的变量为 

final

class ImmutablePoint {
  final num x;
  final num y;
  const ImmutablePoint(this.x, this.y);
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);
}
           

Factory constructors(工厂方法构造函数)

如果一个构造函数并不总是返回一个新的对象,则使用 

factory

 来定义 这个构造函数。例如,一个工厂构造函数 可能从缓存中获取一个实例并返回,或者 返回一个子类型的实例。

下面代码演示工厂构造函数 如何从缓存中返回对象。

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

  // _cache is library-private, thanks to the _ in front
  // of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

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

  Logger._internal(this.name);

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

Methods(函数)

Instance methods(实例函数)

对象的实例函数可以访问 

this

。 例如下面示例中的 

distanceTo()

 函数 就是实例函数:

import 'dart:math';

class Point {
  num x;
  num 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);
  }
}
           

Getters and setters

Getters 和 setters 是用来设置和访问对象属性的特殊 函数。每个实例变量都隐含的具有一个 getter, 如果变量不是 final 的则还有一个 setter。 你可以通过实行 getter 和 setter 来创建新的属性, 使用 

get

 和 

set

 关键字定义 getter 和 setter:

class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  // Define two calculated properties: right and bottom.
  num get right             => left + width;
      set right(num value)  => left = value - width;
  num get bottom            => top + height;
      set bottom(num value) => top = value - height;
}

main() {
  var rect = new Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);
  rect.right = 12;
  assert(rect.left == -8);
}
           

Abstract methods(抽象函数)

实例函数、 getter、和 setter 函数可以为抽象函数, 抽象函数是只定义函数接口但是没有实现的函数,由子类来 实现该函数。如果用分号来替代函数体则这个函数就是抽象函数。

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...
  }
}
           

Abstract classes(抽象类)

使用 

abstract

 修饰符定义一个 抽象类—一个不能被实例化的类。 抽象类通常用来定义接口, 以及部分实现。如果你希望你的抽象类 是可示例化的,则定义一个 工厂 构造函数。

抽象类通常具有 抽象函数。 下面是定义具有抽象函数的 抽象类的示例:

// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer {
  // ...Define constructors, fields, methods...

  void updateChildren(); // Abstract method.
}
           

Implicit interfaces(隐式接口)

每个类都隐式的定义了一个包含所有实例成员的接口, 并且这个类实现了这个接口。如果你想 创建类 A 来支持 类 B 的 api,而不想继承 B 的实现, 则类 A 应该实现 B 的接口。

一个类可以通过 

implements

 关键字来实现一个或者多个接口, 并实现每个接口定义的 API。 例如:

// A person. The implicit interface contains greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person(this._name);

  // In the interface.
  String greet(who) => 'Hello, $who. I am $_name.';
}

// An implementation of the Person interface.
class Imposter implements Person {
  // We have to define this, but we don't use it.
  final _name = "";

  String greet(who) => 'Hi $who. Do you know who I am?';
}

greetBob(Person person) => person.greet('bob');

main() {
  print(greetBob(new Person('kathy')));
  print(greetBob(new Imposter()));
}
           

Enumerated types(枚举类型)

枚举类型通常称之为 enumerations 或者 enums, 是一种特殊的类,用来表现一个固定 数目的常量。

enum Color {
  red,
  green,
  blue
}
           

Adding features to a class: mixins(多重继承)

Mixins 是一种在多类继承中重用 一个类代码的方法。

使用 

with

 关键字后面为一个或者多个 mixin 名字来使用 mixin。 下面是示例显示了如何使用 mixin:

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

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

           

Class variables and methods(类变量和函数)

使用 

static

 关键字来实现类级别的变量和函数。

Generics(泛型)

通常情况下,使用一个字母来代表类型参数, 例如 E, T, S, K, 和 V 等。

abstract class Cache<T> {
  T getByKey(String key);
  setByKey(String key, T value);
}
           

Using parameterized types with constructors(在构造函数中使用泛型

var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var nameSet = new Set<String>.from(names);
           

Libraries and visibility

Using libraries(使用库)

使用 

import

 来指定一个库如何使用另外 一个库

import 'dart:html';
           

Specifying a library prefix(指定库前缀)

如果你导入的两个库具有冲突的标识符, 则你可以使用库的前缀来区分。 例如,如果 library1 和 library2 都有一个名字为 Element 的类, 你可以这样使用

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element();           // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.
           

Importing only part of a library(导入库的一部分)

// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
           

参考文档:http://dart.goodev.org/guides/language/language-tour