第2回関西Kotlin勉強会で発表してきたよ〜 #ashiyakt
Kotlin M13で追加されたsealed class
Kotlin マイルストーン13 がリリースされました!
lateinit
修飾子については↓の記事をば。
Kotlin M13で追加されたlateinit試してみた - 算譜王におれはなる!!!!
sealed class
クラスに付けられるsealed
修飾子が追加されました。
一言で言うと、クラスの継承を制限するための修飾子です。
sealed
が付いたクラスを継承するにはある条件を満たす必要があるということです。
そういう意味でScalaのsealed
と似ていてC#のそれとは異なります。
肝心のsealed classを継承するための条件ですが、現時点ではsealed classにネストされたクラスであることです。
sealed class A { class B: A() } class C: A() // これはダメ
そのうち、この制限を緩和して同一ソースファイル内での継承も許可するそうです。
さて、このsealed classですが何の役に立つのかと言うと、リリースノート内でAlgebraic Data Types(代数的データ型)というキーワードが登場しています。 例えば列挙型をenum classではなくsealed classとそのサブクラスで表現可能です。
sealed class Color { object Red: Color() object Green: Color() object Blue: Color() } val name = when(color) { Color.Red -> "赤" Color.Green -> "緑" Color.Blue -> "青" }
when式の分岐でelse
がないことに注目してください。
Color
はsealed class
として定義されており、他の場所でそのサブクラスが定義されないことを保証します。
そのためwhen式の分岐でRed
、Green
、Blue
すべての場合が考慮されていることをコンパイラは知っているのでelse
が不要になります。
Color
がopen class
として定義された場合には、他の場所でもそのサブクラスが定義される可能性があるのでコンパイラはwhen式にelse
を要求します。
次に、sealed classを使って直和型を表現してみます。
import Option.* sealed class Option<out T> { class Some<T>(val value: T): Option<T>() object None: Option<Nothing>() } val name = when (userOption) { is Some<User> -> userOption.value.name is None -> "null" }
便利ですね〜。
ちなみにインタフェースにはsealed
を付けられないみたいです。
Kotlin M13で追加されたlateinit試してみた
Kotlin マイルストーン13 がリリースされました!
その中で追加されたlateinit
というプロパティにつける修飾子が便利そう。
プロパティの初期化を先延ばしにできるので既存のフレームワークにインジェクトしてもらえるって寸法です。
「プロパティの初期化の先延ばし」っていうとDelegated propertyを思い出すけど、これには問題があったのでした。。
lateinitってDelegates.nonNull()でも同じことできるんじゃないの
— たろう (@ngsw_taro) 2015, 9月 16
@ngsw_taro バイトコード見ると、「private final Lkotlin/properties/ReadWriteProperty; _hello$delegate」ってなってるので、型がちがくてインジェクションしてもらえなくて(´・ω・`)
— しおしお (@_siosio_) December 3, 2014
ということでlateinit
を試してみました。
import com.google.inject.Guice import javax.inject.Inject import kotlin.properties.Delegates class Greeter { fun greet() { println("Hello") } } class Client { @Inject lateinit val greeter1: Greeter @Inject val greeter2: Greeter by Delegates.notNull() } fun main(args: Array<String>) { val injector = Guice.createInjector() val client = injector.getInstance(Client::class.java) client.greeter1.greet() //=> Hello client.greeter2.greet() // IllegalStateException thrown }
Google Guiceでインジェクトしています。
lateinit
が付いているgreeter1
は見事インジェクトされています!しかし、Delegates.notNull()
をつけているgreeter2
はインジェクトされておらずgreet()
呼び出し時に初期化が済んでないよと例外が投げられてしまいました。
そのほかの変更点についてはまた後ほど。
ちなみにこれならいける
var greeter2: Greeter by Delegates.notNull() @Inject set
第3回かわいいKotlin勉強会を開催しました #jkug
開催しました!!!
第3回です!!
44名の方にご来場いただきました。 申し込み自体はキャンセル混みで86名です。 すごい人気です。
会場をご提供してくださいましたドリコム様(@sue445さん)、 運営スタッフの@yy_yankさんにこの場をお借りして感謝申し上げます。
発表資料
Kotlinらしいコード (私)
Server Side Kotlin (@yy_yankさん)
個人開発AndroidアプリをKotlinにガチ移行してみた話 (@kiriminさん)
Kotlin as an AltJS (@mike_neckさん)
(あやぴーさん)
普段C#使っている僕から見た、Kotlin (@RyotaMurohoshiさん)