Kotlin M9まとめ
昨日のエントリで話したPlatform Type以外のM9で改善された言語機能について紹介するよ。
Non-local returns
コードの通りです。
関数リテラル内でのreturn
が出来るよって話。
このコードを実行すると「1」だけ表示される。
fun main(args: Array<String>) { invoke { println("1") return // M9より前ではコンパイルエラー } println("2") } inline fun invoke(f: () -> Unit) { f() }
No more local object declarations
M9より前では関数内にオブジェクト宣言を置けた。
// M9より前 fun foo() { object Point { var x = 0.0 var y = 0.0 } }
これがM9からダメになった。 代わりにオブジェクト式を使う。
// M9 fun foo() { // ↓コンパイルエラーになる // object Point { // var x = 0.0 // var y = 0.0 // } // オブジェクト式で代替 val point = object { var x = 0.0 var y = 0.0 } }
platformStatic
Java用にstaticメソッドを定義できるようになった!
platformStatic
というアノテーションを付けるだけ。
import kotlin.platform.platformStatic object Foo { fun hoge() {} platformStatic fun fuga() {} } class Bar { class object { fun piyo() {} platformStatic fun hage() {} } }
上記のKotlinで定義した関数はJavaで次のように呼び出せる。
// Java
Foo.INSTANCE$.hoge();
Foo.fuga();
Bar.OBJECT$.piyo();
Bar.hage();
platformName
Kotlinでは例えば下記のようなコードを書ける。
2つの同名の関数succ
があるけど、引数がInt
のOptional
とChar
のOptional
。
これを同時に定義できて、呼び出し時も区別してくれる。すごい。
でもJavaではそんなことは無理なのでJava用に別名を付ける必要がある。
そこでplatformName
アノテーションを使う。これはJava用のメソッド名をパラメータに取る。
package sample import java.util.Optional import kotlin.platform.platformName fun succ(n: Optional<Int>) = n.map { it + 1 } platformName("succOfChar") fun succ(c: Optional<Char>) = c.map { (it + 1).toChar() } fun main(args: Array<String>) { println(succ(Optional.of(5))) // => Optional[6] println(succ(Optional.of('K'))) // => Optional[L] }
// Java import sample.SamplePackage; import java.util.Optional; public class Java { public static void main(String[] args) { SamplePackage.succ(Optional.of(5)); SamplePackage.succOfChar(Optional.of('K')); } }
ちなみに何気なくOptional#map
を呼び出して関数リテラルを食わせてるけど、M9からSAM変換が改善されたみたい。
そういえばKotlinのSAM変換がM9で、デフォルト実装をもった関数インタフェースに対しても効くようになってた!
— たろう (@ngsw_taro) 2014, 10月 17
Private property accessors
コード見てもらえばわかると思う。
trait Foo { fun getFoo(): Int } // M9より前だとコンパイルエラー class FooImpl(private val foo: Int): Foo { override fun getFoo(): Int = 0 }
Foo
トレイトを継承したらばpublic
なgetFoo()
を実装する義務を負うけど、これとprivate
なプロパティfoo
が今までは競合して上手くいかなかった。でもM9からは大丈夫!