2015/03/27 このエントリーをはてなブックマークに追加 はてなブックマーク - 【Kotlin】M11(マイルストーン11)の目玉、Companion Objectとlamdaと関数オブジェクト

【Kotlin】M11(マイルストーン11)の目玉、Companion Objectとlamdaと関数オブジェクト





JetBrains社サイトより引用




前回はKotlinのM11で変わったポイントでAndroid向けのものを紹介しました。
【Kotlin】M11(マイルストーン11)はAndroid開発者のためにある


ただ、その他にも大きな変化があったんです。
新規機能や変更が多いので何回かに分けてこのブログで書いていこうと思います。


今回はCompanion Objectとlambdaの変更、関数オブジェクトの変更について翻訳します。


注:翻訳について


===================== 以下、Kotlinブログの翻訳 =============================








おそらく御存知の通り、Kotlinはstaticなメンバ変数は持てない。
代替として、特別なシングルトンオブジェクトをクラスに関連付けてた。
これをclass objectと読んでてイケてないワードだった。
そこで我々はコンセプトを少し再設計した。そしてあなたたちユーザーの意見を聞き、
companion objectと名付けることにした。

As you all probably know, Kotlin classes do not have static members.
Instead there may be a special singleton object associated with a class, which we used to call “class object” ‐ a rather unfortunate term.
So, we somewhat redesigned the concept, and, with your help, chose another name for it: companion object.



単純にイケてない名前を変えたってだけではなくて、
よりオブジェクトらしい振る舞いを考えて再設計した。
The unfortunate wording was not the only reason for this change. In fact, we redesigned the concept so that it is more uniform with normal objects.

クラスはたくさんのシングルトンと名付けられたオブジェクトを
ネスト出来る(出来た)ことに注意してください。

Note that a class can (and always could) have many objects (usual, named singletons) nested into it:


class KotlinClass {
    object Obj1 { ... }
    object Obj2 { ... }
    ...
}


M11以前の、このようなobjectキーワードはcompanion objectで置き換えることが出来る。
メンバーは、クラス名から直接アクセス出来るようになるってわけ。
Since M11, one of these objects may be declared with the companion modifier,
which means that its members can be accessed directly through class name:




class KotlinClass {
    object Obj1 { ... }
    companion object Obj2 { ... }
    ...
}
Obj1にアクセスするときKotlinClass.Obj1.foo()って書かなきゃいけない。
Obj2はこれがオプショナルになる。つまりKotlinClass.foo()と書ける。

Accessing members of Obj1 requires qualification: KotlinClass.Obj1.foo(). For members of Obj2 the object name is optional: KotlinClass.foo().

最終ステップとして、companion objectの名前も削れるよ。
コンパイラはデフォルトネームを勝手に使ってくれる。
One last step: the name of a companion object can be omitted (the compiler will use the default name Companion in this case):


class KotlinClass {
    object Obj1 { ... }
    companion object { ... }
    ...
}
今や、メンバをcompanion objectを含むクラスから参照することが出来る。このように。
 KotlinClass.foo()
もしくは省略せずに書くと
KotlinClass.Companion.foo()




今やあなたはKotlinClass.foo()か省略せずにKotlinClass.Companion.foo()でメンバを参照することが出来るようになった。
Now you can still refer to its members though the name of the containing class: KotlinClass.foo(),
or through full qualification: KotlinClass.Companion.foo().



ご覧のように、これまでのKotlinのclass objectとは違い、companion objectは完全に一般的なオブジェクトと全く一緒だ。
As you can see, unlike what we used to have with class objects, companion objects are completely uniform with normal objects.


もう1つの重要なメリットがある。
いまやすべてのobjectは、無名オブジェクトではないということ。
(companion objectの名前を省略した場合は、再度、companionが使用されている) つまり、companion objectの拡張関数を使えるようになるんだ!
Another important benefit is that now every object has a name (again, Companion is used when the name of a companion object is omitted),
which enables writing extension function for companion objects:



こんな感じで。


fun KotlinClass.Companion.bar() { ... }


詳しくはドキュメントを見てね。

See user docs here.






Kotlinは高階関数を持ってる。
つまり関数を値として受け渡しできるってことなんだけど、M11の前は
2通りの方法があった。

・ラムダ式 (例 { x -> x + 1 })
・呼び出し参照 (例 MyClass::myFun)
M11では新たにとってもロジカルなものを紹介するよ。


Kotlin has higher-order functions,
which means that you can pass a function around as a value. Before M11,
there were two ways of obtaining such values: lambda expressions (e.g. { x -> x + 1 }) and callable references (e.g. MyClass::myFun).
M11 introduces a new one, which is very logical, if you think about it:



例えばあなたがこういうのを考えるとき

val f = fun (x: Int): Int { return x + 1 }


そうつまり、あなたは関数を値としてこういう伝統的な構文形式で
使うことが出来るようになったよ!

詳しくは ユーザードキュメント 仕様書 をみてね。

So, you can use a function, in its traditional syntactic form,
as a value. See user docs and the spec document for more details.





ラムダのパラメータマルチ宣言をサポートすることに向けて、
関数式を提供することにした。
Among other things, function expressions enable us to make a step toward supporting multi-declarations in parameters of lambdas.


最終目標は(まだ実装してないけど)、こんな感じの構文を持つ
ペアのリストをフィルタリングできるようにすること。

pairs.filter { (a, b) -> a != b }

The final goal (not implemented yet) is to be able to, say, filter a list of pairs with the syntax like this:





(a、b)は、マルチ宣言である各ペアのオブジェクトのaは1つ目のcomponentを取得し、 bは二つのcomponentを取得する。 現在、マルチ宣言はサポートされてないけど、我々はM12でマルチ宣言をドロップし、
現在のラムダの構文形式の一部を非推奨にするつもりだ


Here, (a, b) is a multi-declaration, i.e. a gets the first component of each Pair object, and b gets the second one. Currently, multi-declarations are not supported, but we deprecated some of the syntactic forms of lambdas to drop them in M12 and make the multi-declaration syntax possible.
何が非推奨になるかというと、

・ラムダの戻り値の型、例えばを指定する{ (a: Int): Int -> a + 1 }
・ラムダのパラメータ名の周りに括弧を使用した { (a, b) -> a + b }

あなたがこれらを必要とする時は、代わりに関数式を使用するように切り替えてね。


What is deprecated:
specifying return types of lambdas, e.g. { (a: Int): Int -> a + 1 }
specifying receiver types of lambdas: { Int.(a: Int) -> this + a }
using parentheses around parameter names of lambdas: { (a, b) -> a + b }
Whenever you really need one of these, please switch to using function expressions instead.


関数式への切り替えはIDEのクリックフィックスで自動的にやってくれるよ

The IDE provides a quick-fix that migrates your code automatically.


ラムダは、指定された明示的な戻り値の型を持っている場合、ローカルスコープの値のリターンしか許されなかった。
長い間、ラムダにリターン式を使用するにはこういう制限があった。
これは、型推論アルゴリズムの制限が原因だったんだよね。
さて、制限が削除され、ローカルスコープのリターンを自由に使用することが出来るようになった。

list.map {
    if (it < 10) return@map DEFAULT
    ...
}


For a long time there was a restriction on using return expressions in lambdas: a local return was only allowed if the lambda has an explicit return type specified. This was caused by a limitation in the type inference algorithm. Now, the restriction is removed, and we can use local returns freely:







ということで、今回はCompanion Object、lambda、関数オブジェクトなどについて翻訳しました。

・Companion Object
Companion Objectにより、実質staticな変数や関数のサポートしたと言えます。
また、staticな関数を拡張関数として簡易に実装できるようになりました。


・lambda


lambdaに関してはまだ発展途上で、マルチパラメータ対応をしているところです。
多少のシンタックスの変更があってもIDEのサポートが手厚いので問題無いと思います。

・関数オブジェクト

関数オブジェクトとしてfun・・・が持てるようになったので、
見慣れた形式で表現できるようになりました。
JavaScriptなどを普段使っている方にとっては嬉しい変更ではないでしょうか。


次回はKotlinのリフレクションについて翻訳しようと思います。

Don't by shy, try Kotlin!!!!


0 件のコメント:

コメントを投稿