每隔一段时间,总有一种新(或较新)的语言进入大家的视线,比如 Kotlin, Rust, Go 等,我查了一下它们的 “出生日期”:
由于 Dart 1 实质上已经被放弃,Dart 2 改动很大几乎就是一种新的语言,因此这里只列出 v2.0 的日期。
一个现象:这些新出的热门语言,都是静态类型语言,其原因可能是现代 IDE 发展起来了。 动态语言最大的优势是 “写起来省键盘”,但在类型推导与现代 IDE 的加持之下, 静态语言写起来不再繁琐,反而动态语言由于更难进行静态分析而难以享受 IDE 提供的更多好处。
言归正传,从上面各语言的日期可见,其中 Dart 2 非常新,这使得它有机会尽情吸收其它语言的经验, 反映出现代编程语言的很多新思想。下面开始说说 Dart 语言的特点。
甚至连数字都是对象,比如下面的例子,数字可直接调用方法:
// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');
由于一切皆对象,所以任何变量的默认值都是 null,比如:
int n;
String s;
assert(n == null);
assert(s == null);
直接在代码内写 assert()
, 这个函数只在开发环境中有效,而在生产环境中会被忽略,非常适合用来做一些简单但重要的测试。
以前的静态类型语言一般要求每次定义变量时,都明确写明类型,这非常繁琐。 而现在自动推导变量类型这个特性几乎成为了各种新语言的标配,不少老牌语言也在新版中加入这个特性。
var s = 'abc';
assert(s.runtimeType.toString() == 'String');
不通过 public, protected, private 等关键词来表明成员是否对外公开,而是通过首字母来表示。 类似于 Golang, Golang 是用首字母大写表示 public, 但这被很多开发者诟病,确实会带来一些不便。 而 Dart 则是用首字母为下划线来表示 private, 这就比 Golang 那种设定舒服多了,也很符合直觉。
// 这个例子只是为了说明访问权限,并非最佳实践。
class MyClass {
int _count;
int get count => _count;
set count(value) => _count = value;
}
是不是有点像 Python? 但与 Python 不同的是,_count
不是看起来像 private, 而是真的 private !
这也是新语言中比较流行的一种特性,确实非常好用。
int n;
// 此时 n == null, 可以赋值。
n ??= 3;
assert(n == 3);
// 此时 n != null,保留原来的值。
n ??= 5;
assert(n == 3);
print(1 ?? 3); // 结果为 1.
print(null ?? 5); // 结果为 5.
myObject?.someProperty
// 如果没有问号语法,就会麻烦很多:
(myObject != null) ? myObject.someProperty : null
关于 null 有一个故事,他的发明者曾说这是自己犯下的 “十亿美元错误”(billion-dollar mistake)。 但这么多年过去了,新语言明明有机会采用 “无 null” 设计,却还是选择了有 null, 侧面说明这个发明还是好处多过坏处。
比如 filter(在 Dart 里是 where), map, any, fold 等等,以前常见于动态类型语言,但由于这些函数确实很方便, 现在很多静态语言里也是标配特性了。
numbers
.where((n) => n % 2 == 0)
.forEach((n) => print(n));
在下面的例子中,x
和 y
拥有默认的 getter 和 setter,非常方便。
class Point {
num x, y;
Point(this.x, this.y);
}
var p = Point(1.2, 3);
p.y = 2.5;
print('${p.x}, ${p.y}'); // "1.2, 2.5"
Kotlin 也有类似的特性。为什么在已经有了那么多编程语言的情况下,还要不断发明新的语言呢, 原因之一就是这些新特性非常优雅:写起来更方便,读起来更清晰。
据说是微软 C# 最先发明的 async/await 语法(我没有查证),用过都说好,甚至连 JavaScript 和 Python 都在版本升级中加入了这种语法。
在本文开头列出的多种语言之中,Go 由于拥有独特的 goroutine 而不需要 async/await, 另外 Swift 虽然暂时没有这种语法,但开发者呼声很高,后续大概率会加上,列表中的其他语言全都已经具备这种语法了。
Future main() async {
var ver = await getVersion();
print('In main: version is $ver');
}
如果你曾经主要使用 JavaScript, 后来转到别的语言,那么你可能会很怀念那个可爱又实用的胖箭头。 在 Dart 里你可以再次愉快过使用它。
class MyClass {
int value = 0;
void increase() => value++;
}
Dart 自称是专为客户端(约等于前端)而设计的语言,而这个新颖、高效的串联语法很好地体现了什么叫做 客户端语言,这是 Dart 带给我最大的惊喜!
querySelector('#confirm')
..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
以上列举了 Dart 的一部分特性,可以看出它吸收了很多新特性,同时考虑了别的语言的使用习惯, 学起来会有一种“似曾相识”的熟悉感,用起来会有一种“要啥有啥”的爽感。
再结合它的强大生命力:通过 Flutter 在手机端生存,通过编译为高质量的 JavaScript 代码在网页端生存, 通过编译为二进制可执行文件在桌面电脑端生存,同时也已经被 Google 官方确定为 Fuchsia 的主要编程语言之一。 因此,有兴趣的同学不妨学习一下。
(漏了一个重要特性没有讲……)
这是一个神奇的功能,Kotlin 里有,Rust 里也有,没有在其他语言里见过了。
假如我们想对第三方库、或者标准库里的类增加方法,但又不能(或不想)修改其源码,没有问题,在我们自己的代码里这样写:
extension NumberParsing on String {
// 在这里可以当作在 String 类里面一样写代码
int parseInt() {
return int.parse(this);
}
}
这样扩展之后,只要在引入了 NumberParsing 在地方,任何字符串都具有 parseInt 方法了。
'42'.parseInt()
1
chinvo 2020-03-21 23:13:14 +08:00 via iPhone
最后还是要编译成 js,和 ts 比也没有太大优势
|
2
cmdOptionKana OP @chinvo 网页端不是 Dart 的主战场(曾经是,但早就完败了,借助 Flutter 还魂)
|
3
itning 2020-03-21 23:45:54 +08:00 via Android
刚出 1.0 的时候学过,写了个 app,嵌套的无法想象
|
4
cmdOptionKana OP @itning 是指 Flutter 1.0 吧? Flutter 我还没学不太了解,据说嵌套是特色,但看起来 Flutter 发展得挺快的,不知道现在有什么变化没。
|
5
fan123199 2020-03-22 00:41:00 +08:00
说起这些特性,我还是想起了 kotlin 。kotlin 的语法糖还多一些。
|
6
fan123199 2020-03-22 00:41:42 +08:00
不过作为 Android 开发,后面还是要继续学 kotlin 。😀
|
7
cmdOptionKana OP @fan123199 Kotlin 添加语法特性简直疯狂,非常激进,好处是魔法多、表现力强大,缺点是需要更多时间去熟悉。Dart 还是比较克制的,学起来更轻松一些。
|
8
laike9m 2020-03-22 02:26:54 +08:00 via Android
你列的很多特性在 Dart 1 里就有了。cascade 确实好,我也很喜欢。
|
9
WebKit 2020-03-22 03:16:25 +08:00 via Android
@chinvo 优势还是有的,比如我这种不会 web 开发的人,做个简单的 app 然后编译一下,全平台都走了。有点类似 rn,不过流畅性上比 rn 强很多
|
10
sagaxu 2020-03-22 08:43:18 +08:00 via Android
干不了服务端
|
11
secondwtq 2020-03-22 10:34:30 +08:00
有几点我觉得楼主有必要提一下(如果有的话):
* 继承(单继承?多继承?能不能继承 int 等类型?) * 有没有类似 Java/Go Interface 的机制? * Operator Overloading/Ad-hoc Polymorphism * 有没有泛型?或者干脆 大 道 至 简? |
12
mrcn 2020-03-22 10:45:07 +08:00 via Android
Append 的那个 ,C#也有
|
13
mxalbert1996 2020-03-22 11:50:19 +08:00 via Android
扩展方法我见过的最强大的还是 Swift
|
14
cmdOptionKana OP @secondwtq
Dart 是单继承的,然后提供 Mixin 来解决一些原本需要多继承的场景(这好像也是目前比较流行的方案,因为多继承用起来不容易处理好)。 不能继承 int, double, bool, Null 和 String,但可以扩展方法。 Dart 的每一个 class 都会自动成为 interface (即每一个 class 都可以被 implement ),但一般不建议 implement 普通类,官方建议需要 interface 的时候就用 abstract class 。 有 Operator Overloading 。(那个 ad-hoc Polymorphism 我不懂…) 有泛型的,除了 Go 谁还敢玩大道至简(狗头)。 |
15
cmdOptionKana OP |
16
Tecrafter 2020-03-22 13:08:40 +08:00
有预感使用 Dart 的 Flutter 会一统大前端。
|
17
w4mxl 2020-04-09 16:35:54 +08:00
@cmdOptionKana #7 很同意~
|