Flutter之路-Dart篇

Dart的一些基础知识能够看Dart中文网,网上也有不少入门教程。这个系列只是我在学习过程颇有用,但一些基础教程中未说起的。json

Dart和Java在不少方面很类似,但也有不少不同的地方,好比:ide

  • 在 Dart 中没有诸如 public、private、protected 这样的关键词。以 _ 开头,则该标识符 在库内是私有的
  • Dart2中,能够不使用new关键字建立,也可使用。
  • Dart中一切都是对象,方法也是对象而且具备一种类型Function。
  • Dart中变量初始值为null,即便是int类型也是null。
  • ..........

函数

可选参数

  1. 可选命名参数函数

    调用方法的时候,你可使用这种形式 paramNamevalue 来指定命名参数。例如:
    enableFlags(bold: true, hidden: false);

    在定义方法的时候,使用 {param1param2, …} 的形式来指定命名参数:学习

    /// Sets the [bold] and [hidden] flags to the values
    /// you specify.
    enableFlags({bool bold, bool hidden}) {
      // ...
    }

    可选命名参数经常使用于类的构造函数,看参看类-构造函数可选命名参数ui

  2. 可选位置参数this

    把一些方法的参数放到 [] 中就变成可选 位置参数了:
    String say(String from, String msg, [String device]) {
      var result = '$from says $msg';
      if (device != null) {
        result = '$result with a $device';
      }
      return result;
    }

    下面是不使用可选参数调用上面方法 的示例:code

    assert(say('Bob', 'Howdy') == 'Bob says Howdy');

    下面是使用可选参数调用上面方法的示例:对象

    assert(say('Bob', 'Howdy', 'smoke signal') ==
        'Bob says Howdy with a smoke signal');

     

Dart中类的定义、继承、重载和Java差很少,若是你会Java那Dart的面向对象也就很简单。但仍是存在一些差别性的地方继承

例如:实列化的时通常是new Point();,Dart中new是可选的,Java是必须的。教程

 

构造函数

常见的构造函数定义和Java同样,定义一个和类名字同样的方法就定义了一个构造函数,还能够带有其余可选的标识符:

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

 

构造函数可选命名参数

在看Flutter一些控件的源码时,常常能看到如下代码

const Text(this.data, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
  }) : assert(data != null),
       textSpan = null,
       super(key: key);

构造函数也是函数,因此一样适用函数的可选命名参数,在加上Dart 提供了一个语法糖,因此可像如下代码调用

new Text('红色+黑色删除线+25号',
    style: TextStyle(
        color: const Color(0xffff0000),
    ),
)

初始化参数列表

在构造函数体执行能够初始化实例参数, 使用逗号分隔初始化表达式。

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

警告: 初始化表达式等号右边的部分不能访问 this

初始化列表很是适合用来设置 final 变量的值。

重定向构造函数

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

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

调用超类构造函数

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

若是超类没有无名无参数构造函数, 则你须要手工的调用超类的其余构造函数。 在构造函数参数后使用冒号 (:) 能够调用 超类构造函数。

class Person {
  String firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}

main() {
  var emp = new Employee.fromJson({});

  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
  }
  (emp as Person).firstName = 'Bob';
}

下面是构造函数执行顺序:

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