Flutter 面试知识点:Dart 强类型语言

2019年5月14日21:18:30 发表评论 46 views

学习过 JavaScript 或者 Java/Kotlin 的人,在学习 Dart 上几乎是没什么难度的,Dart 综合了动态语言和静态语言的特性, 这里主要提供一些不一样,或者有意思的概念。

  • 1、Dart 属于是强类型语言 ,但可以用 var 来声明变量,Dart自推导出数据类型var 实际上是编译期的“语法糖”。dynamic 表示动态类型, 被编译后,实际是一个 object 类型,在编译期间不进行任何的类型检查,而是在运行期进行类型检查。
  • 2、Dartif 等语句只支持 bool 类型,switch 支持 String 类型。
  • 3、Dart数组和 List 是一样的。
  • 4、Dart 中,Runes 代表符号文字 , 是 UTF-32 编码的字符串, 用于如 Runes input = new Runes('\u{1f596} \u{1f44d}');
  • 5、Dart 支持闭包。
  • 6、Dart 中 number 类型分为 int 和 double ,没有 float 类型。
  • 7、Dart级联操作符 可以方便配置逻辑,如下代码:
event
  ..id = 1
  ..type = ""
  ..actor = "";
复制代码
  • 8、赋值操作符

比较有意思的赋值操作符有:

AA ?? "999"  ///表示如果 AA 为空,返回999
AA ??= "999" ///表示如果 AA 为空,给 AA 设置成 999
AA ~/999 ///AA 对于 999 整除
复制代码
  • 9、可选方法参数

Dart 方法可以设置 参数默认值指定名称

比如: getDetail(Sting userName, reposName, {branch = "master"}){} 方法,这里 branch 不设置的话,默认是 “master” 。参数类型 可以指定或者不指定。调用效果: getRepositoryDetailDao(“aaa", "bbbb", branch: "dev");

  • 10、作用域

Dart 没有关键词 publicprivate 等修饰符,_ 下横向直接代表 private ,但是有 @protected 注解 。

  • 11、构造方法

Dart 中的多构造方法,可以通过命名方法实现。

默认构造方法只能有一个,而通过 Model.empty() 方法可以创建一个空参数的类,其实方法名称随你喜欢,而变量初始化值时,只需要通过 this.name 在构造方法中指定即可:

class ModelA {
  String name;
  String tag;
  
  //默认构造方法,赋值给name和tag
  ModelA(this.name, this.tag);

  //返回一个空的ModelA
  ModelA.empty();
  
  //返回一个设置了name的ModelA
  ModelA.forName(this.name);
}
复制代码
  • 12、getter setter 重写

Dart 中所有的基础类型、类等都继承 Object ,默认值是 NULL, 自带 gettersetter ,而如果是 final 或者 const 的话,那么它只有一个 getter 方法,Object 都支持 getter、setter 重写:

  @override
  Size get preferredSize {
    return Size.fromHeight(kTabHeight + indicatorWeight);
  }
复制代码
  • 13、Assert(断言)

assert 只在检查模式有效,在开发过程中,assert(unicorn == null); 只有条件为真才正常,否则直接抛出异常,一般用在开发过程中,某些地方不应该出现什么状态的判断。

  • 14、重写运算符,如下所示重载 operator 后对类进行 +/- 操作。
class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
  
  ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}
复制代码

支持重载的操作符 :

Flutter 面试知识点:Dart 强类型语言
  • 类、接口、继承

Dart 中没有接口,类都可以作为接口,把某个类当做接口实现时,只需要使用 implements ,然后复写父类方法即可。

Dart 中支持 mixins ,按照出现顺序应该为extendsmixinsimplements

  • Zone

Dart 中可通过 Zone 表示指定代码执行的环境,类似一个沙盒概念,在 FlutterC++ 运行 Dart 也是在 _runMainZoned 内执行 runZoned 方法启动,而我们也可以通过 Zone ,在运行环境内捕获全局异常等信息:

  runZoned(() {
    runApp(FlutterReduxApp());
  }, onError: (Object obj, StackTrace stack) {
    print(obj);
    print(stack);
  });
复制代码

同时你可以给 runZoned 注册方法,在需要时执行回调,如下代码所示,这样的在一个 Zone 内任何地方,只要能获取 onData 这个 ZoneUnaryCallback,就都可以调用到 handleData

///最终需要处理的地方
handleData(result) {
  print("VVVVVVVVVVVVVVVVVVVVVVVVVVV");
  print(result);
}

///返回得到一个 ZoneUnaryCallback 
var onData = Zone.current.registerUnaryCallback<dynamic, int>(handleData);

///执行 ZoneUnaryCallback 返回数据
Zone.current.runUnary(onData, 2);

复制代码

异步逻辑可以通过 scheduleMicrotask 可以插入异步执行方法:

Zone.current.scheduleMicrotask((){
  //todo something
});
复制代码

更多可参看 :《Flutter完整开发实战详解(十一、全面深入理解Stream)》

  • Future

Future 简单了说就是对 Zone 的封装使用。

比如 Future.microtask 中主要是执行了 ZonescheduleMicrotask ,而 result._complete 最后调用的是 _zone.runUnary 等等。

  factory Future.microtask(FutureOr<T> computation()) {
    _Future<T> result = new _Future<T>();
    scheduleMicrotask(() {
      try {
        result._complete(computation());
      } catch (e, s) {
        _completeWithErrorCallback(result, e, s);
      }
    });
    return result;
  }

复制代码

Dart 中可通过 async/await 或者 Future 定义异步操作,而事实上 async/await 也只是语法糖,最终还是通过编译器转为 Future

有兴趣看这里 :

generators

code_generator.dart

Flutter完整开发实战详解(十一、全面深入理解Stream)

  • Stream

Stream 也是有对Zone 的另外一种封装使用。

Dart 中另外一种异步操作, async* / yield 或者 Stream 可定义 Stream 异步, async* / yield 也只是语法糖,最终还是通过编译器转为 Stream Stream 还支持同步操作。

1)、Stream 中主要有 StreamStreamControllerStreamSinkStreamSubscription 四个关键对象,大致可以总结为:

  • StreamController :如类名描述,用于整个 Stream 过程的控制,提供各类接口用于创建各种事件流。
  • StreamSink :一般作为事件的入口,提供如 addaddStream 等。
  • Stream :事件源本身,一般可用于监听事件或者对事件进行转换,如 listenwhere
  • StreamSubscription :事件订阅后的对象,表面上用于管理订阅过等各类操作,如 cacenlpause ,同时在内部也是事件的中转关键。

2)、一般通过 StreamController 创建 Stream;通过 StreamSink 添加事件;通过 Stream 监听事件;通过 StreamSubscription 管理订阅。

3)、Stream 中支持各种变化,比如mapexpandwheretake 等操作,同时支持转换为 Future

作者:恋猫de小郭
来源:掘金

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: