200行代码快速入门Dart语法

以下是本人对Dart语法和机制探索的代码,对于有其他编程语言基础(和Dart的语法最像的是Java)的朋友而言,看懂这段200行的代码就基本会Dart的常用语法了。

可惜csdn的markdown不支持Dart,高亮有一点问题,这里采用了js的高亮。将就着看吧。

import 'dart:async';
import 'dart:mirrors';

// 没有public修饰,通过下划线开头的命名控制访问
class Father {
  // 成员变量
  // 字符串填充可用美元符,带大括号可以用长表达式,不带大括号只能填充单个变量名
  // as 用于类型强制转换
  String memberVariable = "some text ${print('assigning to member by initialization') as Null}";
  // 计算属性getter,使用时相当于一个成员变量,但仅限读取,例如String something = this.computed + "suffix";
  // 单表达式作为返回值的函数可以写成箭头形式
  get computed => "$memberVariable and some other ${print("calling getter") as Null}";
  // setter 计算属性setter,使用时相当于一个成员变量,但仅限写入,例如this.computed = "new text"
  set computed(String value) =>  print('calling setter'); // 字符串用单/双引号均可
  // 实例方法
  instanceMethod(String parameter) {
    print("calling instance method");
    try {
      double x = 7 / 2; // 浮点数除法
      int y = 7 ~/ 2; // 整数除法
      if (x != y) { throw Error(); }
    } on Error /* 捕捉类型,可选*/ catch (error/* 存储异常对象的变量名,必选 */, stacktrace /* 存储调用栈对象的变量,可选 */) {
      print(error);
      print(stacktrace);
      rethrow; // 重新抛出异常
    } finally { print("in finally scope"); }
  }
  // static member 静态成员,下划线开头为private,外部不可见
  static Father _staticMember = null;
  // static method 静态方法
  static staticMethod(String parameter) =>  print("calling static method");
  // default constructor 构造函数,未定义任何构造函数时会隐式声明无参的默认构造函数
  Father() {print("calling default constructor");}
  // named constructor 命名构造函数
  // this.memberVariable 作为参数,一键搞定成员赋值
  Father.named(this.memberVariable) {print("calling named constructor");}
  // factory constructor 工厂构造函数,可以不返回新实例
  factory Father.factoryConstructor(String parameter) {
    if (Father._staticMember == null) {
      Father._staticMember = new Father.named(parameter); // new 是可选的,也可以写成Father.staticMember = Father.named(parameter);
    }
    return _staticMember;  // 和Java一样,同一个类里可以省略不写类名访问静态字段
  }
}
// mixin 混入
mixin SomeMixIn {
  // mixin 不能有构造函数,其余与类基本一致
  void mixinMethod() {
    final message = "do"; // final只可以修饰变量和成员变量
    const detail = "something"; // const用于声明编译时常量
    // final和const修饰都可以推断变量的类型
    print(message + detail);
  }
}

// Dart的interface关键字已被删除,但所有类都对应一个隐式接口,固可用抽象类代替接口声明
// 由此也可以写出诸如 class StepFather implemets Father {...} 的代码
abstract class Interface {
  // 抽象方法不需要加abstract修饰
  abstractMethod();
}

class Son extends Father /* 单继承 */ with SomeMixIn /* 多混入 */ implements Interface /* 多实现 */ {
  // 构造函数无法被继承,显式调用父类构造函数需要这样写
  Son(): super(){}
  Son.named(String paramter): super.named(paramter) {}
  // override 重写
  @override
  instanceMethod(String parameter) {
    print("calling override method");
    try { 
      super.instanceMethod(parameter);  // 调用父类方法
    } catch(e) {}
  }
  // 可以利用混入实现一些代码的复用,或者用于“代替”多继承
  void someMethod() => this.mixinMethod(); 
  // 实现抽象方法
  @override
  abstractMethod() => print("abstract method implementation"); 
}

// 全局变量,属于package的命名空间
// {}作为表达式是空Map的语法糖,如果想解释成Set需要有元素,如{"a"}
// dynamic用于声明动态的类型
Map<Type, dynamic> instanceOf = {
  // 类名也是全局变量,类型是Type
  Father: Father() // Father()是new Father()的省略写法
};

// 定义函数作为一种类型
typedef TypeToMethodMirrorFunction = MethodMirror Function(Type);

// 全局函数,属于package的命名空间
MethodMirror getConstructor(Type type) {
  // 函数reflectClass 来自包 dart:mirrors
  var classMirror = reflectClass(type);  // var 声明变量能将变量的类型推断为表达式的类型
  Map<Symbol, DeclarationMirror> declarations = classMirror.declarations;  // 手动声明类型也可以,但是会长一点
  MethodMirror constructor; // 不初始化为null
  // 迭代器循环
  for (var item in declarations.entries) {
    print(item);
    // 元数据反射:item.value.metadata
    var value = item.value;
    // 实例类型判断用is而不是instanceof,相反逻辑用is!
    if (value is MethodMirror) {
      if (value.constructorName == Symbol.empty) {
        // 跳过默认构造函数
        continue;
      }
      if (value.isConstructor) {
        constructor = value;
        break;
      }
    }
  }
  return constructor;
}

// 使用定义过的类型来声明变量
TypeToMethodMirrorFunction anotherName = getConstructor;

// 反射实例
reflectDemo() {
  // Map插入/读取键值是对通过索引而不是set(key, value)/get(key)
  // []是List的语法糖
  instanceOf[Son] = reflectClass(Son).newInstance(Symbol.empty, []); // 使用默认构造函数实例化
  var constructor = anotherName(Son);
  // 断言,非调试模式会被忽略,可附加断言失败的信息
  assert(constructor != null && constructor.isConstructor, "constructor var is not constructor!");
  InstanceMirror instanceMirror = reflectClass(Son)
      .newInstance(constructor.constructorName, ["parameter"]);
  Father father = instanceMirror.reflectee // 此处类型转换是dynamic转换成Father,运行时可能会出错
                  ..instanceMethod("parameter") // 级联调用,可以非常方便地访问第一个表达式的成员
                  ..computed += "nonsense"; // 级联调用也可以调用getter和setter
  print(constructor.parameters); // 获得反射出方法的参数列表
  // 通过反射对成员变量赋值
  reflect(father).setField(#computed, "new value"); // #computed是Symbol("computed")的语法糖
  print(
    // 函数式迭代
    instanceOf.entries.firstWhere(
      (MapEntry<Type, dynamic> entry) { // anonymous function 匿名函数,参数类型可不声明,因为在这里参数的类型能够被推断
        return entry.value.runtimeType == Father;
      }
    )
  );
}

// 异步实例,异步函数应当返回Futrue,但在函数体内的return语句可直接返回Futrue泛型变量的类型的值,而不需要创建Future
// 命名参数x和hasDefault,hasDefault是带默认值的命名参数
Future<int> asyncAdd({int x, int hasDefault = 0}) async {
  print("actual hasDefault: ${hasDefault}");
  return ++x; // 也可以写 return Future.microtask(()=>++x);
}

// 可选位置参数,不声明类型默认为dynamic,p2是带默认值的可选位置参数
Future<void> asyncDemo([p1, dynamic p2 = "string"]) async {
  onSuccess(int v) => print("async call success with $v") as Null; // 返回值需要不为void才能作为Futrue.then/catchError的回调函数
  onError(dynamic e) =>  print("async call error with:\n$e") as Null; 
  // 不传递x,++x产生空指针异常
  int x = await asyncAdd().then(onSuccess).catchError(onError);
  print("async function returned $x");
  // 命名参数的传递方式
  x = await asyncAdd(x: 114514, hasDefault: 1919).then(onSuccess).catchError(onError);
  print("async function returned $x");
}

// 生成器实例
generatorDemo() {
  for(int result in generator()) { // 同步生成器可以使用for-in迭代,因为本质是Iterable
    print("generator generated ${result}");
  }
  Stream<int> stream = asyncGenerator(10); // 异步生成器返回流,可以附加监听函数
  stream.listen((value) => print("stream value: $value"));
}

Iterable<int> generator() sync* {
  for(var item in  [1,2,3]) {
    yield item;
  }
  yield* subGenerator();  // 相当于将某个Iterable对象的迭代生成逐个yield
}

Iterable<int> subGenerator() sync* {
  yield -1;
  yield -2;
}

// 异步生成器
Stream<int> asyncGenerator(int count) async* {
  if (count == 0) { return; }
  yield count--;
  yield* asyncGenerator(count);
}

// 主函数,执行入口
main(List<String> args) {
  reflectDemo();
  Future.value(asyncDemo()).then((v){}).catchError((){}); // 先同步后异步,因此输出在后面
  generatorDemo();
}

运行输出:

assigning to member by initialization
calling default constructor
assigning to member by initialization
calling default constructor
MapEntry(Symbol("instanceMethod"): MethodMirror on 'instanceMethod')
MapEntry(Symbol("someMethod"): MethodMirror on 'someMethod')
MapEntry(Symbol("abstractMethod"): MethodMirror on 'abstractMethod')
MapEntry(Symbol("Son"): MethodMirror on 'Son')
MapEntry(Symbol("Son.named"): MethodMirror on 'Son.named')
assigning to member by initialization
calling named constructor
calling override method
calling instance method
Instance of 'Error'
#0      Father.instanceMethod (file:///c:/Coding/Playgrounds/playground.dart:21:21)
#1      Son.instanceMethod (file:///c:/Coding/Playgrounds/playground.dart:72:13)
#2      reflectDemo (file:///c:/Coding/Playgrounds/playground.dart:133:21)
#3      main (file:///c:/Coding/Playgrounds/playground.dart:198:3)
#4      _startIsolate. (dart:isolate-patch/isolate_patch.dart:305:32)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)

in finally scope
calling getter
calling setter
[ParameterMirror on 'paramter']
calling setter
MapEntry(Father: Instance of 'Father')
actual hasDefault: 0
generator generated 1
generator generated 2
generator generated 3
generator generated -1
generator generated -2
async call error with:
NoSuchMethodError: The method '+' was called on null.
Receiver: null
Tried calling: +(1)
async function returned null
actual hasDefault: 1919
async call success with 114515
async function returned null
stream value: 10
stream value: 9
stream value: 8
stream value: 7
stream value: 6
stream value: 5
stream value: 4
stream value: 3
stream value: 2
stream value: 1

你可能感兴趣的:(dart)