第一眼看起来,Dart的语法有点像Java/C#/JavaScript,据说是为了让人们容易上手。不过Dart有它自己的原则和特点,这导致它和它们在某些方面是有明显的不同,还是得花一些时间思考和研究的。
首先是语法上一些比较熟悉的特性:
一些比较独特的特性:
Dart提供了可选的类型系统,在声明变量、定义函数的时候,可以指定类型,也可以不指定,不指定的话就是dynamic。
Dart的类型系统比较独特的地方在于,类型仅仅是给编辑器和编译器看的,它不应也不会对代码的行为产生任何影响。在production模式下,类型会被忽略,以获得更好的性能。我们在执行dart代码时,可以指定-checked参数,打开或关闭运行时的类型检查(默认未开启)。
由于类型系统不对代码行为产生影响,所以没法通过参数类型来区分两个同名方法,没法进行重载。同时也没法实现像C#中的扩展方法,即声明一个static方法:
public static void fullName(User user) { return user.firstName + user.lastName; }
然后调用:
User user = getUserFromSomewhere(); user.fullName();
开发团队说正在想其它办法提供类型的功能。
所以我们只能把类型看作是对编辑器的提示,可用来让编辑器帮我们提示方法、变量,以及检查我们调用时是否打错了字。也因此我们可以实现一些在别处做不到的魔术:随便给一个变量指定任意一个类型,让编辑器帮我们提示,同时利用noSuchMethod(),来处理我们对该对象的调用:
class User { String name; } class Animal { String roaring; } class Ghost { noSuchMethod(Invocation msg) { // handle missing invocations } } User user = new Ghost(); user.name = "Freewind"; Animal animal = new Ghost(); animal.roaring = "hahaha";
Dart运行在自己的虚拟机DartVM上,它跟nodejs所在的v8有点像。虽然有了虚拟机,但并不像java/c#那样,下面还有一些字节码,Dart本身就相当于字节码。关于这个选择,开发团队在一个文章中说了很多原因,不过最后总结为一句:对于Dart来说,使用字节码没有更多好处,使用Dart语言本身也没有更多坏处,所以就没搞字节码了。
关于线程,Dart代码运行于单线程环境中,这跟nodejs很像。这意味着我们不需要担心多线程的那些锁啊同步什么的问题,就算对一个全局变量进行读写,也不用考虑会不会被其它线程改了(当然还是建议少使用全局变量)。dart内置库中提供了Future,很多IO或耗时的操作,都返回的是Future对象,然后在它的then()方法中传个回调进去,这跟nodejs也是很像的。好在Dart直接内置了这种标准做法,不像js那里,有无数的库想来解决这个问题。
由于单线程无法很好的利用多核,所以Dart提供了一个 isolate库。我们在可以在自己的代码中,使用spawnFunction(…)函数,新起一个isolate出来,执行指定的函数。一个isolate跟一个线程有点像,比如普通的Dart代码也是运行在一个isolate中。但不同的是,两个isolate之间是不共享内存的,所以同一个全局变量,在不同的isolate中是互相独立的,改了这边不会影响那样。这样看起来,每个isolate像是一个进程。两个isolate之间可以互相发消息进行通信,风格有点像actor,消息会clone后发出去。除了通过spawnFunction()指定函数启动外,还可以spawnUrl指定另一个dart文件来启动,然后也之通信。如果是前者,可以传各种对象当消息,如果是后者,只能传一些基本类型,比如string,int之类,作用就有限了。
Dart是一门很保守的语言。虽然看它的介绍“要替代JavaScript”时,以为它会是一个比较动态的语言,实际上相当静态。比如:
不支持eval(),不能动态执行一段Dart代码。官方说这是基于性能的考虑,js里不是也不建议使用eval吗?
不能动态添加方法。不过提供了noSuchMethod作为解决方案,可以做到相似的效果
不能导入修改后的代码、不能动态扩展代码。这点比较郁闷,因为就算在java中,我们也可以通过classloader来读取新代码,加入到当前的运行时中,提供新功能。而在Dart中,目前仅有一个spawnUrl能以一种非常有限、基本没用的方式来模拟。这导致我们没法在不重启的情况下,执行新生成的代码(如模板引擎)。
官方在发布Dart的同时,也提供了一个基于eclipse的Dart Editor,功能还比较丰富,高亮、格式化、代码检查、重构、单步调试等都有了。只是不能跟eclipse结合起来,因为不是插件形式。这让人感觉不太方便,因为很多有用的eclipse插件都用不了了。
Idea也提供了一个Dart的插件,基本功能也有,但有些功能有问题,比如调试用不了,代码检查经常不正常。终于Idea有Dart上落后于eclipse了。
另外,sublime也提供了Dart的高亮文件,但其它功能都比较弱。
我现在基本上就是同时开着IDEA和Eclipse,基本操作在Idea中完成,遇到问题时,切换到Eclipse看看它的错误提示,不能不说,这还是非常有用的。
Dart的开发团队还是相当活跃的,我相信Dart现在那些比较弱的地方,很快就会有改进的。现在非常希望它增加类型于“扩展方法”和“动态导入”这两个功能,不然感觉很多想法都实现不了。
(看到上面的代码又乱了吗!最痛恨wordpress的就是这个了,白排了半天版。所以要尽快把我的dartblog弄好转过去。)