最近学习 Dart 语言,分享一下心得 (入门级) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cmdOptionKana
3.16D
V2EX    Dart

最近学习 Dart 语言,分享一下心得 (入门级)

  •  
  •   cmdOptionKana 2020-03-21 22:42:57 +08:00 5978 次点击
    这是一个创建于 2104 天前的主题,其中的信息可能已经有所发展或是发生改变。

    每隔一段时间,总有一种新(或较新)的语言进入大家的视线,比如 Kotlin, Rust, Go 等,我查了一下它们的 “出生日期”:

    • Rust (2011 自举, 2015 v1.0)
    • Go (2012, v1.0)
    • Kotlin (2012 开源, 2016 v1.0)
    • TypeScript (2014, v1.0)
    • Swift (2014, v1.0)
    • Dart/Flutter (2018, Dart v2.0)

    由于 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); 

    代码内测试 (inline testing)

    直接在代码内写 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 !

    用问号语法来简化 null 相关操作

    这也是新语言中比较流行的一种特性,确实非常好用。

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

    自动提供 getter, setter

    在下面的例子中,xy 拥有默认的 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++; } 

    串联语法 (Cascade)

    Dart 自称是专为客户端(约等于前端)而设计的语言,而这个新颖、高效的串联语法很好地体现了什么叫做 客户端语言,这是 Dart 带给我最大的惊喜!

    querySelector('#confirm') ..text = 'Confirm' ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); 

    总结

    以上列举了 Dart 的一部分特性,可以看出它吸收了很多新特性,同时考虑了别的语言的使用习惯, 学起来会有一种“似曾相识”的熟悉感,用起来会有一种“要啥有啥”的爽感。

    再结合它的强大生命力:通过 Flutter 在手机端生存,通过编译为高质量的 Javascript 代码在网页端生存, 通过编译为二进制可执行文件在桌面电脑端生存,同时也已经被 Google 官方确定为 Fuchsia 的主要编程语言之一。 因此,有兴趣的同学不妨学习一下。

    第 1 条附言    2020-03-22 10:30:43 +08:00

    (漏了一个重要特性没有讲……)

    扩展方法 (extension methods)

    这是一个神奇的功能,Kotlin 里有,Rust 里也有,没有在其他语言里见过了。

    假如我们想对第三方库、或者标准库里的类增加方法,但又不能(或不想)修改其源码,没有问题,在我们自己的代码里这样写:

    extension NumberParsing on String { // 在这里可以当作在 String 类里面一样写代码 int parseInt() { return int.parse(this); } } 

    这样扩展之后,只要在引入了 NumberParsing 在地方,任何字符串都具有 parseInt 方法了。

    '42'.parseInt() 
    17 条回复    2020-04-09 16:35:54 +08:00
    chinvo
        1
    chinvo  
       2020-03-21 23:13:14 +08:00 via iPhone
    最后还是要编译成 js,和 ts 比也没有太大优势
    cmdOptionKana
        2
    cmdOptionKana  
    OP
       2020-03-21 23:28:17 +08:00
    @chinvo 网页端不是 Dart 的主战场(曾经是,但早就完败了,借助 Flutter 还魂)
    itning
        3
    itning  
       2020-03-21 23:45:54 +08:00 via Android
    刚出 1.0 的时候学过,写了个 app,嵌套的无法想象
    cmdOptionKana
        4
    cmdOptionKana  
    OP
       2020-03-22 00:00:12 +08:00
    @itning 是指 Flutter 1.0 吧? Flutter 我还没学不太了解,据说嵌套是特色,但看起来 Flutter 发展得挺快的,不知道现在有什么变化没。
    fan123199
        5
    fan123199  
       2020-03-22 00:41:00 +08:00
    说起这些特性,我还是想起了 kotlin 。kotlin 的语法糖还多一些。
    fan123199
        6
    fan123199  
       2020-03-22 00:41:42 +08:00
    不过作为 Android 开发,后面还是要继续学 kotlin 。
    cmdOptionKana
        7
    cmdOptionKana  
    OP
       2020-03-22 01:07:34 +08:00
    @fan123199 Kotlin 添加语法特性简直疯狂,非常激进,好处是魔法多、表现力强大,缺点是需要更多时间去熟悉。Dart 还是比较克制的,学起来更轻松一些。
    laike9m
        8
    laike9m  
       2020-03-22 02:26:54 +08:00 via Android
    你列的很多特性在 Dart 1 里就有了。cascade 确实好,我也很喜欢。
    WebKit
        9
    WebKit  
       2020-03-22 03:16:25 +08:00 via Android
    @chinvo 优势还是有的,比如我这种不会 web 开发的人,做个简单的 app 然后编译一下,全平台都走了。有点类似 rn,不过流畅性上比 rn 强很多
    sagaxu
        10
    sagaxu  
       2020-03-22 08:43:18 +08:00 via Android
    干不了服务端
    secondwtq
        11
    secondwtq  
       2020-03-22 10:34:30 +08:00
    有几点我觉得楼主有必要提一下(如果有的话):
    * 继承(单继承?多继承?能不能继承 int 等类型?)
    * 有没有类似 Java/Go Interface 的机制?
    * Operator Overloading/Ad-hoc Polymorphism
    * 有没有泛型?或者干脆 大 道 至 简?
    mrcn
        12
    mrcn  
       2020-03-22 10:45:07 +08:00 via Android
    Append 的那个 ,C#也有
    mxalbert1996
        13
    mxalbert1996  
       2020-03-22 11:50:19 +08:00 via Android
    扩展方法我见过的最强大的还是 Swift
    cmdOptionKana
        14
    cmdOptionKana  
    OP
       2020-03-22 12:38:14 +08:00   1
    @secondwtq

    Dart 是单继承的,然后提供 Mixin 来解决一些原本需要多继承的场景(这好像也是目前比较流行的方案,因为多继承用起来不容易处理好)。

    不能继承 int, double, bool, Null 和 String,但可以扩展方法。

    Dart 的每一个 class 都会自动成为 interface (即每一个 class 都可以被 implement ),但一般不建议 implement 普通类,官方建议需要 interface 的时候就用 abstract class 。

    有 Operator Overloading 。(那个 ad-hoc Polymorphism 我不懂…)

    有泛型的,除了 Go 谁还敢玩大道至简(狗头)。
    cmdOptionKana
        15
    cmdOptionKana  
    OP
       2020-03-22 12:41:02 +08:00
    @mrcn
    @mxalbert1996 原来扩展方法也不罕见啊,第一次见的时候感觉特别强大,也很实用。

    (现在各种主流语言单说语法的话还真的非常共通)
    Tecrafter
        16
    Tecrafter  
       2020-03-22 13:08:40 +08:00
    有预感使用 Dart 的 Flutter 会一统大前端。
    w4mxl
        17
    w4mxl  
       2020-04-09 16:35:54 +08:00
    @cmdOptionKana #7 很同意~
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2775 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 14:40 PVG 22:40 LAX 06:40 JFK 09:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86