Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2013-05-24) Kotlin临忘前小记一下

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

这段时间由于想尝试使用Kotlin来写js代码,所以试用了一下它,主要用它改写了一个angularjs的todomvc的示例,总体感觉还不错,具体过程可参看我的另一个日志。

不过,Kotlin在语法层面,特别是与js结合的方面,还是有一些缺失。另外angularjs本身为了最大的利用js的灵活性,导致使用带类结构的静态语言来编写它时,无法很好的利用上其类结构,写出来的代码总让人觉得有些别扭。所以我决定暂时还是不以Kotlin为主力语言,先观望,等它更成熟一些后再试。

现在Kotlin在jvm端应该能达到可用的程度了,我用的一个idea插件acejump就是用它写的。所以如果有时间,我也许会用Kotlin写写服务器端代码,修改一下这个插件的bug,感受一下idea插件的写法。不过这个就不太确定了,因为现在的工作有点忙。

由于很可能在未来的一段时间里不再接触Kotlin,为了避免到时候完全忘记,所以趁现在小记一下,方便到时候恢复记忆。

Kotlin的定位是比Java强大,但比Scala易用,位置处于两者的中间偏scala一点。它的竞争对手xtend,处于两者中间偏java一点。Scala中的大部分特性在Kotlin中都有所体现,但是Kotlin为了能让做法简单一点,简化了Scala中的一些较复杂的概念,一些复杂的特性也没有提供,不像scala那么函数式。在Kotlin中更多体现的是对java的改进,所以对于Java程序员来说,上手会比较快和自然。

在Kotlin中,有类、有包,没有public字段,而是属性。比如在User类中定义了val name:String,实际上它会生成get_name和set_name这两个方法供使用,而name变成了$name被隐藏起来。这在与js交互时不太方便,因为我们在js中,很少会使用getter/setter,两者结合起来各种别扭。

Kotlin中有trait,trait和interface之间的区别是trait中定义的方法可以带实现,而不像interface那样必须是空的。一个类可以继承多个trait,如果两个trait中有同名的方法,则我们可以在代码是指定使用哪个超类的方法,而不像Scala那样,它们实际上是个链,嵌套在一起。Kotlin的这种实现比较简单和直观,而Scala的作法可以实现AOP。

Kotlin中有object,它声明在一个class的内部,通常用作工厂方法,不像Scala那样可以单独声明。对了,Kotlin中也可以用object关键字后面带一个类似JSON那样格式的声明,实现一个单例对象。这点记不太清,不想去查资料了。

Kotlin可以扩展某个类,添加字段或者方法。它的语法跟ruby有点像,即fun String.abc() = {} 这样的形式。

Kotlin中定义方法用的关键字是fun而不是def,这在最开始时还有一些争论,很多人支持用def。后来作者说fun写起来会让人感觉开心,同时想突出一下function的概念,所以用fun。不过现在fun定义出来的感觉更像是方法,而不是函数,不能像函数值那样当参数传给其它函数。这有点不太方便,不过据说很快会加上一个语法::method,把method转为function value。

在Kotlin中可执行代码不能放在顶层,必须放在一个方法里,比如main()。这一点在生成js代码时不太方便,因为我们必须手写一行js代码,去找到并调用那个main()执行初始化操作。

Kotlin中有一个native关键字,在写js代码时很常用,因为我们经常需要引用一些由第三方库提供的js对象或方法,这时可用native标记一下,实现就写成noImpl,它就只起到了一个声明的作用。Kotlin中的变量不能使用$,它被Kotlin内部使用了,而在js中这个需要经常用,如果需要我们可写成native(“\$scope”) var scope这样的形式,让它生成的js变量与我们在Kotlin中使用的不一样。

Kotlin中可以声明函数字面量,形如{(a:String, b:Int): User -> User(a,b) },这种形式有时候有点啰嗦,特别是有嵌套的时候。我希望能提供这样的写法:(a:String,b:int):User -> { User(a,b) }或 { a:String, b:Int -> User(a,b) },但被作者否决了。

Kotlin中有类型推断,像Scala一样,在声明变量,传入函数字面量时,可以少写很多类型,还是很方便的。

Kotlin中没有return,行尾也不需要写分号。

Kotlin的集合也提供了很多好用的如filter这样的方法,可以这么用:list.filter { it > 2 map { it*2 }

Kotlin的函数,如果最后一个是() -> Any类型,则可以把它拿到外面,用花括号括起来写。这样可以实现一些dsl,如html builder。例如:html { body { … } }

Kotlin中的 () -> Any类型的函数,如果写成函数字面量,则是 { mycode },而不需要像Scala那样写成:() => { mycode }。由于Kotlin这种写法比较简单,所以不需要Scala中的传名参数,少了个概念,但可以做同样的事。这样想想,似乎Scala的传名函数不太有必要。(或者有其它的好处我还不知道?)

Kotlin中使用in和out这两个关键字来表示逆变和协变,写成,相比Scala中的-T和+T,简单很多,让人一看就能记住。如果是传函数中传,就可以声明为,如果是返回值,就声明为

在Kotlin中,有一个有趣的特性是null safety,在声明一个变量时,可以在类型后面加个?,如var s :String?。如果有问号,表示它可能为null,在使用时必须先判断一下它不等于null,否则编译不过。这跟Scala的Option[String]相比,概念和写法上都要简单很多,更有Java的味道。我想吐槽一下Scala的Option[String],写起来很麻烦,用起来getOrElse也不很爽,特别是有时候有嵌套,如Option[Option[String]]的时候,让人欲哭无泪。

Kotlin中还有一个特性叫代理。据说使用它可以有一些特别的好处,不过这个东西我比较陌生,所以没法展开,以后再好好看看。

语法方面的,现在只能想到这么多了,应该照顾到大部分了。没有去翻文档,因为想不起来的可能都不是那么重要了。

最后是IDE方面,使用Idea的Kotlin插件,体验还是很流畅的,错误提供等很快捷,不像Scala那么卡。但IDE的功能还没有Java那么强,还有不少的改进空间。

最后祝福Kotin,在Andrey的领导下能更快的成熟起来,因为它是我在以后替代Java的一个有力候选者。

comments powered by Disqus