これはKotlin Advent Calendar 2014の23日目の投稿になります。
もう1年近くKotlinを触ってない身なのですが、是非カレンダー書いてくれ!と言われたので、ない知見を絞り出して書こうとしたのですが、気付いたらカレンダーも全部埋まり、みんなどんどん書いてくるのでKotlinの未来は変態安泰だなと思いました。
そんなことなので、とりあえずリハビリ的にKotlin Koansというのをやってみることにしました。いわゆるチュートリアルです。みなさんはもうやっていましたらすみません。
Kotlin Koansは、githubにリポジトリがあるので、それをcloneしてテストを流しながら課題を説いていったらKotlinのことわかるかもよ?ということだと思います。英語なので何言ってんのかわからないものもあったりしたのですが、とりあえずテストが通るようにしていけばいいんじゃないでしょうか。masterリポジトリが課題で、resolutionsリポジトリが答え(解答例)になります。わからないものは、解答例を見ながら考えてみるといいのではないかと思います。
とりあえず解きながら、その中で得られた知見をツラツラと書いていこうと思います。
i_introduction > _5_Nullable_Types
fun todoTask5(client: Client?, message: String?, mailer: Mailer) = TODO(
“””
Task 5.
Rewrite JavaCode5.sendMessageToClient to kotlin (using only one ‘if’).
Declarations of Client, PersonalInfo and Mailer are given below.
“””,
references = { JavaCode5().sendMessageToClient(client, message, mailer) }
)
JavaCode5.sendMessageToClientをKotlinで書き直せ(ただし、ifは1回な!)
だそうです。
public class JavaCode5 extends JavaCode { public void sendMessageToClient(@Nullable Client client, @Nullable String message, @NotNull Mailer mailer) { if (client == null || message == null) return; PersonalInfo personalInfo = client.getPersonalInfo(); if (personalInfo == null) return; String email = personalInfo.getEmail(); if (email == null) return; mailer.sendMessage(email, message); } }
最初は特になにも考えずにおりゃーと書いてみたのですが、下のような感じ。
fun sendMessageToClient( client: Client?, message: String?, mailer: Mailer ) { if (client == null || message == null) return val personalInfo = client.personalInfo!! val email = personalInfo.email!! mailer.sendMessage(email, message) }
こんな感じで書いたらテストで!!のところでぬるぽが発生してダメでした。
目的のデータは、emailなわけです。なので、以下のように書いてみました。
fun sendMessageToClient( client: Client?, message: String?, mailer: Mailer ) { if (client?.personaiInfo?.email == null || message == null) return mailer.sendMessage(client?.personalInfo?.email, message) }
if式以降はclient?.personalInfo?.emailはnullでないことが証明されているのでこれでよかったんや!!めっちゃ短くなりました。Kotlinすごい。
iii_properties > 19_LazyProperty
遅延評価を行うには、Delegates.lazyを使うのが普通と思っていました。
しかし、課題はDelegates.lazyを使わずに遅延評価してみろというものでした。
以下のようにすれば、できるようです。
class LazyProperty(val initializer: () -> Init) { private val lazyValue: Int? = null get() { if ($lazyValue == null) $lazyValue = initializer() return $lazyValue } val lazy: Int get() = lazyValue!! }
iii_properties > 20_DelegatesExamples
Delegates.mapVarとかDelegates.mapValとか初めて知りました。
プロパティをHashMapに委譲できるので便利ですね!
class Commodity(data: MutableMap<String, Any?>) { // data.get("description")の値を取得 val description: String by Delegates.mapVal(data) // data.get("price")の値を取得 var price: Int by Delegates.mapVar(data) // data.get("isAvailable")の値を取得 var isAvailable: Boolean by Delegates.mapVar(data) }
iv_builders > 24_TheFunctionWith
withメソッドで変数を囲むことで、ブロック内のスコープ上でその変数がthisになります。builderのような処理だと何度も書いたりすることがあるので、これは良さそうですね。
fun buildString(): String { val builder = StringBuilder() with(builder) { append("Numbers: ") for(i in 1..10) { append(i) } } return builder.toString() }
syntax > classesObjectsTraits
Kotlinはクラス定義がコンストラクタになるから、プライベートコンストラクタを作るとき、このように書くようです。
クラス名の直後にprivateと書くのはなんか忘れてしまいそう…。
class ClassWithPrivateConstructor private(val bar: Int) { class object { fun newInstance() = ClassWithPrivateConstructor(9) } }
その他、一通りやってみました。collectionのところなどは、filterメソッドやmapメソッドを使って簡潔に書く方法などを、テストを通して学ぶ事ができるので、間違っているかどうかもすぐにわかります。
久々にKotlinを書いてみましたが、コレクションの扱いなどはやりやすくてやっぱりいい言語だなーと思います。
普段はRubyばかり書いているのでなかなか触る機会が少ないのですが、来年は!来年こそは!!