熟悉dart的语法

WuYiLong原创大约 7 分钟flutterdart

配置dart的环境

因为当你在电脑上已配好fullter时,dart的sdk早已内嵌到flutter-sdk开发包里,附上下载地址: flutter-sdkopen in new window

配置vscode

首先在扩展里面安装dart和flutter,如图
dart
这样就可以在vscode上愉快的撸代码了

语法

变量

var -声明的变量不用指定变量类型 const 修饰类中的变量,则必须加上 static 关键字 final 修饰的是运行时的常量 const 修饰的是编译时的常量 变量名加下划线是私有的,以下划线(_)开头的成员仅在代码库中可见

类型转换

// String -> int var one = int.parse('1'); // String -> double var onePointOne = double.parse('1.1'); // int -> String String oneAsString = 1.toString(); // double -> String String piAsString = 3.14159.toStringAsFixed(2);

可选参数

  • 命名参数 void enableFlags({bool bold, bool hidden}) {...}
  • 位置参数 使用 [] 将一系列参数包裹起来作为位置参数
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}
  • 默认参数 可以用 = 为函数的命名和位置参数定义默认值,默认值必须为编译时常量,没有指定默认值的情况下默认值为 null。
void enableFlags({bool bold = false, bool hidden = false}) {...}

级联运算符(..)

级联运算符(..)可以让你在同一个对象上连续调用多个对象的变量或方法。

 querySelector('#confirm') // 获取对象 (Get an object).
  ..text = 'Confirm' // 使用对象的成员 (Use its members).
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

返回值

所有的函数都有返回值。没有显示返回语句的函数最后一行默认为执行 return null;。

条件表达式

如果赋值是根据布尔表达式则考虑使用 ?:。

var visibility = isPublic ? 'public' : 'private';
如果赋值是根据判定是否为 null 则考虑使用 ??。
String playerName(String name) => name ?? 'Guest';

获取对象的类型

可以使用 Object 对象的 runtimeType 属性在运行时获取一个对象的类型,该对象类型是 Type 的实例。

子类调用父类的构造函数

class Employee extends Person {
  Employee() : super.fromJson(defaultData);
  // ···
}

初始化列表

除了调用父类构造函数之外,还可以在构造函数体执行之前初始化实例变量。每个实例变量之间使用逗号分隔。

// Initializer list sets instance variables before
// the constructor body runs.
// 使用初始化列表在构造函数体执行前设置实例变量。
Point.fromJson(Map<String, num> json)
    : x = json['x'],
      y = json['y'] {
  print('In Point.fromJson(): ($x, $y)');
}

重定向构造函数

有时候类中的构造函数会调用类中其它的构造函数,该重定向构造函数没有函数体,只需在函数签名后使用(:)指定需要重定向到的其它构造函数即可:

class Point {
  num x, y;

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

  // 委托实现给主构造函数。
  Point.alongXAxis(num x) : this(x, 0);
}

Getter 和 Setter

Getter 和 Setter 是一对用来读写对象属性的特殊方法,上面说过实例对象的每一个属性都有一个隐式的 Getter 方法,如果为非 final 属性的话还会有一个 Setter 方法,你可以使用 get 和 set 关键字为额外的属性添加 Getter 和 Setter 方法:

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

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

  // 定义两个计算产生的属性:right 和 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;
}

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

抽象类

// This class is declared abstract and thus
// can't be instantiated.
// 该类被声明为抽象的,因此它不能被实例化。
abstract class AbstractContainer {
  // 定义构造函数、字段、方法等……

  void updateChildren(); // 抽象方法。
}

隐式接口

// A person. The implicit interface contains greet().
// Person 类的隐式接口中包含 greet() 方法。
class Person {
  // _name 变量同样包含在接口中,但它只是库内可见的。
  final _name;

  // 构造函数不在接口中。
  Person(this._name);

  // greet() 方法在接口中。
  String greet(String who) => '你好,$who。我是$_name。';
}

// Person 接口的一个实现。
class Impostor implements Person {
  get _name => '';

  String greet(String who) => '你好$who。你知道我是谁吗?';
}

String greetBob(Person person) => person.greet('小芳');

void main() {
  print(greetBob(Person('小芸')));
  print(greetBob(Impostor()));
}

扩展一个类

使用 extends 关键字来创建一个子类,并可使用 super 关键字引用一个父类:

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

重写类成员

子类可以重写父类的实例方法、Getter 以及 Setter 方法。你可以使用 @override 注解来表示你重写了一个成员

class SmartTelevision extends Television {
  @override
  void turnOn() {...}
  // ···
}

枚举类型

枚举类型是一种特殊的类型,也称为 enumerations 或 enums,用于定义一些固定数量的常量值。

enum Color { red, green, blue }

使用 Mixin 为类添加功能

定义一个类继承自 Object 并且不为该类定义构造函数,这个类就是 Mixin 类,除非你想让该类与普通的类一样可以被正常地使用,否则可以使用关键字 mixin 替代 class 让其成为一个单纯的 Mixin 类:

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

Mixin 是一种在多重继承中复用某个类中代码的方法模式。 使用 with 关键字并在其后跟上 Mixin 类的名字来使用 Mixin 模式:

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

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

可以使用关键字 on 来指定哪些类可以使用该 Mixin 类,比如有 Mixin 类 A,但是 A 只能被 B 类使用,则可以这样定义 A:

mixin MusicalPerformer on Musician {
  // ···
}

使用集合字面量

var names = <String>['小芸', '小芳', '小民'];
var uniqueNames = <String>{'小芸', '小芳', '小民'};
var pages = <String, String>{
  'index.html': '主页',
  'robots.txt': '网页机器人提示',
  'humans.txt': '我们是人类,不是机器'
};

限制参数化类型

class Foo<T extends SomeBaseClass> {
  // 具体实现……
  String toString() => "'Foo<$T>' 的实例";
}

class Extender extends SomeBaseClass {...}

这时候就可以使用 SomeBaseClass 或者它的子类来作为泛型参数:

var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();

使用泛型方法

T first<T>(List<T> ts) {
  // 处理一些初始化工作或错误检测……
  T tmp = ts[0];
  // 处理一些额外的检查……
  return tmp;
}

指定库前缀

如果你导入的两个代码库有冲突的标识符,你可以为其中一个指定前缀。比如如果 library1 和 library2 都有 Element 类,那么可以这么处理:

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// 使用 lib1 的 Element 类。
Element element1 = Element();

// 使用 lib2 的 Element 类。
lib2.Element element2 = lib2.Element();

异步函数

  • Future
Future checkVersion() async {
  var version = await lookUpVersion();
  // 使用 version 继续处理逻辑
}
  • Stream

使用 async 关键字和一个 异步循环(使用 await for 关键字标识)。

Future main() async {
  // ...
  await for (var request in requestServer) {
    handleRequest(request);
  }
  // ...
}

生成器(Generators

当你需要延迟地生成一连串的值时,可以考虑使用 生成器函数。Dart 内置支持两种形式的生成器方法:

同步 生成器:返回一个 Iterable 对象。

异步 生成器:返回一个 Stream 对象。

通过在函数上加 sync* 关键字并将返回值类型设置为 Iterable 来实现一个 同步 生成器函数,在函数中使用 yield 语句来传递值:

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}

实现 异步 生成器函数与同步类似,只不过关键字为 async* 并且返回值为 Stream:

Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

元数据

使用元数据可以为代码增加一些额外的信息。元数据注解以 @ 开头,其后紧跟一个编译时常量(比如 deprecated)或者调用一个常量构造函数。

class Television {
  /// _弃用: 使用 [turnOn] 替代_
  @deprecated
  void activate() {
    turnOn();
  }

  /// 打开 TV 的电源。
  void turnOn() {...}
}

可以自定义元数据注解。下面的示例定义了一个带有两个参数的 @todo 注解

library todo;

class Todo {
  final String who;
  final String what;

  const Todo(this.who, this.what);
}


import 'todo.dart';

@Todo('seth', 'make this do something')
void doSomething() {
  print('do something');
}
上次编辑于:
贡献者: wuyilong