Flutter 面试知识点:Dart 强类型语言
学习过 JavaScript
或者 Java/Kotlin
的人,在学习 Dart
上几乎是没什么难度的,Dart 综合了动态语言和静态语言的特性, 这里主要提供一些不一样,或者有意思的概念。
- 1、
Dart
属于是强类型语言 ,但可以用var
来声明变量,Dart
会自推导出数据类型,var
实际上是编译期的“语法糖”。dynamic
表示动态类型, 被编译后,实际是一个object
类型,在编译期间不进行任何的类型检查,而是在运行期进行类型检查。 - 2、
Dart
中if
等语句只支持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
没有关键词 public
、private
等修饰符,_
下横向直接代表 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
, 自带 getter
和 setter
,而如果是 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));
}
复制代码
支持重载的操作符 :
- 类、接口、继承
Dart
中没有接口,类都可以作为接口,把某个类当做接口实现时,只需要使用 implements
,然后复写父类方法即可。
Dart
中支持 mixins
,按照出现顺序应该为extends
、 mixins
、implements
。
-
Zone
Dart
中可通过 Zone
表示指定代码执行的环境,类似一个沙盒概念,在 Flutter
中 C++ 运行 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
中主要是执行了 Zone
的 scheduleMicrotask
,而 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
。
有兴趣看这里 :
-
Stream
Stream
也是有对Zone
的另外一种封装使用。
Dart 中另外一种异步操作, async*
/ yield
或者 Stream
可定义 Stream
异步, async*
/ yield
也只是语法糖,最终还是通过编译器转为 Stream
。 Stream 还支持同步操作。
1)、Stream
中主要有 Stream
、 StreamController
、StreamSink
和 StreamSubscription
四个关键对象,大致可以总结为:
StreamController
:如类名描述,用于整个Stream
过程的控制,提供各类接口用于创建各种事件流。StreamSink
:一般作为事件的入口,提供如add
,addStream
等。Stream
:事件源本身,一般可用于监听事件或者对事件进行转换,如listen
、where
。StreamSubscription
:事件订阅后的对象,表面上用于管理订阅过等各类操作,如cacenl
、pause
,同时在内部也是事件的中转关键。
2)、一般通过 StreamController
创建 Stream
;通过 StreamSink
添加事件;通过 Stream
监听事件;通过 StreamSubscription
管理订阅。
3)、Stream
中支持各种变化,比如map
、expand
、where
、take
等操作,同时支持转换为 Future
。
作者:恋猫de小郭
来源:掘金