tento.techのtech系()ブログ

tento.techのメンバーが書いているブログです。

第四回Kotlin勉強会のメモとか感想とか

こんにちは。tento.tech広報のそうすけです。TwitterのbioにScalaが好きな高校生とか書いてますしKotlinも好きです。今回はSansanさんのオフィスで行われた第四回kotlin勉強会に参加してきたので、その中で「ほへー」って思ったものをいくつか書いておこうと思います。

そもそもみなさんKotlinご存知?

まずみなさんKotlinってプログラミング言語をご存知ですか?JVM上で動作するプログラミング言語でここ数年Android界隈で話題になっている言語です。Javaより簡潔な記法で書けてヌル安全が保証されていてしかも完全な互換性があってしかも安心安全のJetBrains社製っていうなかなか良いプログラミング言語です。

kotlinでDSL(Yamamoto jumpeiさん)

このLTの中でSMC(State Machine Compiler)をKotlinで実装した話がでていてその中で「ほへー」と思ったものを少し。

operator invoke

class A {
 operator fun invoke (){
   print("this is a")
 }
}

operatorを付けてinvoke関数を定義すると

val a = A()

a() // this is a

A()() //this is a

こんな感じで使えるよ〜、というやつ。ここで定義するinvoke関数はもちろん引数も持てますし、ラムダ式を引数に渡したりすることだってできます。 他にも下の例のように拡張関数として実装することもできるそう。

operator fun String.invoke(){
  print("this is $this"
}

こんな感じで使える

"foo"() //this is foo

infix

もう1つ「ほへー」と思ったのがinfixです。関数にinfixをつけると中置呼び出し(infix calls)が可能になります。

class A {
  infix fun shows(arg: String){
    print(arg)
  }
}

infixをつけてshowsを定義します。すると

val a = A()

a.shows("bar")
a shows "bar"
//両者共にbarと出力する

後者の例のようにJavaでいうメンバ参照演算子(kotlinでもいうのかは知りません)や括弧のない書き方もできるようになります。 最初自分はこのような関数はただの中置呼び出し可能な関数であって中置関数とは呼べないのだと思ってたんですけど、kotlinユーザーグループ代表のたろうさんに尋ねたところ中置呼び出し可能な関数のことをkotlinの仕様上中置関数(infix function)と呼べるそうです。

Java -> Kotlin そのあとに。(辰濱健一さん)

タイトルどおりのお話で、IDEの機能でJavaのコードをKotlinコードに変換するとKotlinっぽさに欠けるちょっと汚いコードになっているから人力で少し直しましょうというお話。このLTの中で「ほへー」と思ったものを。

メンバ変数の接頭辞mははずそう

private String mId;
private TextView mTextView;

を変換すると

private var mId:String? = null
private var mTextView:TextView? = null

こういうkotlinコードになるので、mIdmははずしておこう、ということらしい。というのもはずしておかないと生成されるgetter/setterにmが残ってしまうからだそう。

可能な箇所はvar -> valへ

varは再代入可能な変数、valは再代入不可能な変数です。Javaでいうところのfinal。KotlinやScalaでは極力valを使うことが推奨されていますので、コードの中で再代入がされていない、もしくは一度しか代入が行われていない場合はvalに変更しておくべきですね。

遅延初期化に

初期化するときはby lazy {...}を使って遅延初期化にしたほうがいいらしい

NotNull型にできるならして、!!演算子の除去

Kotlinはヌル安全が保証されているので、NotNull型(型名そのまま)とNullable型(型名の後に?がつく)があります。それでKotlinには!!演算子というのがあります。この演算子は、Nullableな参照を、NotNullに強制変換します。ただ、nullに対して使うとぬるぽが起きるそう。!!は原則使用しないことが推奨されているそうです。

スコープ関数に置き換える

Kotlinにはスコープ関数という便利な関数が4つあります。(let, with, run, apply)それぞれの使い分けに関してはたろうさんのqiita.com を読むとわかりやすいです。で、その置き換えられる箇所はそのスコープ関数に置き換えたほうが簡潔に書けて、Kotlinらしいということらしい。

単一式関数に置き換える

単一式関数は波括弧で囲われていなくてreturnがない関数です

fun add(x:Int, y:Int): Int {
  return x + y
}

fun add(x: Int, y: Int): Int = x + y

に書き換えろってことですね。

if, else if,...はwhenに

when式はJavaでいうswitch文です。変換直後は複数の分岐はif, else ifになっているのでwhenで書き直したほうがいいよということらしいです。

使われていない関数パラメータの型チェック

使われていない関数パラメータの型が実際はNullableなのにNotNullになっていることがあるので、人力でチェックしましょうということらしい。

Mapped TypeとPlatform Typeの話(むろほしさん)

これは簡単にいうとKotlinとJavaは相互互換があるけどそのとき型はどうなるんでしょうかって話です。Kotlinはヌル安全な言語ではあるけどJavaとの相互運用の中ではNullPointerExceptionやIllegalStateExceptionになってしまう可能性もあります。

Platform Type

Platform TypeっていうのはString!のような型名の後に!のある型のことで、簡単にいうとNullableな型でもありNotNullな型でもあります。(String!はString?にもStringにも代入できる)詳しくはむろほしさんの qiita.com を読めばわかりやすいです。そして、原則としてJavaから来たオブジェクトはPlatform Typeになるらしい。

IllegalStateExceptionになる例

Platform TypeをNotNull型に代入する時にそのオブジェクトがnullの場合にIllegalStateExceptionが発生してしまうそうです。

NullPointerExceptionになる例

Platform Typeのメンバにアクセスしようとしたときにそのオブジェクトがnullであった場合NullPointerExceptionになる。 これらはコンパイルエラーにならなくても実行時エラーになるから気をつけようとのこと。

Mapped Type

クラス型はPlatform Typeとして扱われるけどプリミティブ型はMapped Typeとして扱われるみたいです。JavaのintはKotlinではKotlin.Intとして扱われるみたいです。つまり、Javaの基本データ型はKotlinでは固有のTypeとして扱われるということらしいです、初めて知りました。Javaの数値ラッパークラスはKotlinでは対応する型のPlatform Typeになるそうです。(例えば、JavaのIntegerはKotlinではInt!)なので使い方を間違えると IllegalStateExceptionとかNullPointerExceptionが発生するみたい。 このあたりはJavaのコードでメソッドを書くときに@Nullableとか@NotNullをつけることで明示的に示せるようなので、上手に使いましょうということらしい。あとKotlinのInt?はJavaではIntegerだそうです。でもJavaにはオートボクシングがあるので、KotlinのInt?をIntegerに代入しても普通に動きます。

Kotlinの2つのリストインターフェース

kotlin.collections.List<T>

count()とか要素取得とかReadOnlyのメソッドしかない。但し不変リストではない。

kotlin.collections.MutableList<T>

List<T>を継承さらに要素を変更するメソッドを持つ

で、これら2つはjava.util.List<T>として扱われるらしいです。なのでJava側で@ReadOnlyとか@Mutableをつけてメソッドを区別するみたいです。SetやMapでも同じらしい。

Ankoでコンポーネント指向(k-kagurazakaさん)

Androidアプリを作る上でXMでVIewを作るのが色々と辛い箇所があるということでJetBrains製のKotlinでのAndroidアプリ開発におけるいろいろをやってくれるAnkoというライブラリでコンポーネント指向的な感じでViewを構成しようという話らしい。コンポーネント指向ってあれですね、React.jsとかAngular2とかのアレですね。弊コミュニテイにはReactマンが一人いますね。変な人ですが。kotlin1.1の新機能bound call referenceの話とかもあって楽しかったです。ただ、自分がAndroidの話にそこまで詳しくないのでわからない箇所が多々あったり...。今度スライド見直しつつ復讐します。

ラムダ式禁止おじさん(たろうさん)

もうタイトルからネタ臭が漂って来てますけど案の定ネタ的な話でした。まあ簡単に説明するとラムダ式は色々と難しいから関数参照とかカリー化、関数の部分適用を駆使してなんとかしてラムダ式を使わずに書こうという話です。ただこれラムダ式を回避しようとすればするほどトリッキーなコードが生成されていってしかも関数参照は複雑になるとインライン展開されないことが多く、パフォーマンスにも影響が及ぶとかで最終的には「ラムダ式を使いましょう」っていう話になってました。

懇親会

食事がでてきたのも驚きましたけどなにより周りの人と結構話せたのが楽しかったです。僕はディズニーの年パスを持っているんですけど、他にもう二方年パスを持っているガチ勢がいらっしゃっていてずっとディズニーの話をしていました。あと会場のBGMがディズニーランドのエントランスのBGMだったので終始ハイテンションでした。疲れました。

最後に

JavaとかScalaとかが好きでやたらと触っているのですごい楽しかったです。個人的にはweb系の勉強会よりも楽しいと感じました。これに関しては完全に自分の好みですけども。来年もKotlin勉強会あるみたいなのでその時はまた参加したいと思っています。