って前に聞かれたけど、スッと答えられなかったのでここに記します。
※このあたり(https://speakerdeck.com/ntaro/kotlinwoshi-meyouhanzuon-number-droidkaigi-number-droidkaigi6?slide=41)
とりあえずstaticを使いたければ
「objectかcompanion objectを使いましょう」が、対応としては合ってます。
companion object {
@JvmField
val CREATOR: Parcelable.Creator<Repository> = object : Parcelable.Creator<Repository> {
override fun createFromParcel(source: Parcel): Repository =
Repository(source.readLong(),
source.readString(),
source.readString(),
source.readString(),
source.readInt(),
source.readParcelable(Repository::class.java.classLoader),
source.readString())
override fun newArray(size: Int): Array<out Repository?> = kotlin.arrayOfNulls(size)
}
}
staticなCREATORというフィールドが必要な場合は、companion objectを利用して、JvmFieldアノテーションでコンパイラーへの目印とすればコード生成時にclassに属するstaticフィールドと言うかたちでクラスバイトコードを作ってくれるって感じです。
staticがないのは
言語デザイン的にstaticというのは要らんやろというのが理由です。
以下のKotlinのブログに言及があります。
https://blog.jetbrains.com/kotlin/2013/06/static-constants-in-kotlin/
Kotlin is designed so that there’s no such thing as a “static member” in a class. If you have a function in a class, it can only be called on instances of this class. If you need something that is not attached to an instance of any class, you define it in a package, outside any class (we call it package-level functions):
Kotlinはクラスにstatic memberを持たず、任意のクラスのinstanceに対しての関数呼び出しだけになるだろうということです。クラスに属する関数でない場合はパッケージに属する関数呼び出しになる、と。そのいずれかになるのでstaticは要らんだろうということみたいです。
この頃(マイルストーン5.3。メジャーバージョン前の2013年)はJvmFieldアノテーションとかなくて、staticフィールドをクラスバイトコードになった状態で提供する方法が無かった。あと、objectを利用する例が載っていますが、現在ではcompanion objectを利用するようになっています。マイルストーン11での変更です。コレもメジャーバージョン前です。
https://blog.jetbrains.com/kotlin/2015/03/kotlin-m11-is-out/
なんか当時書いてたやつ。↓
【Kotlin】M11(マイルストーン11)の目玉、Companion Objectとlamdaと関数オブジェクト
なんで要らんねん
いやいや、よう分からん。なんで要らんねん。ということもあるでしょう。
という場合はここらへんに書いてることを読むといいかもしれません。Scalaですけど、言ってる内容は同じなので。
http://stackoverflow.com/questions/7302206/why-doesnt-scala-have-static-members-inside-a-class
オブジェクト指向的にstaticとかよろしくないやろみたいなやつです。オブジェクトに属さない存在とはなんだということですかね。
こんなんが出来るのがうわぁ、て感じって話かなと思います。
public static void main(String[] args) { String str = ((String) (null)).valueOf(123); BigDecimal ten = ((BigDecimal) (null)).TEN; System.out.println(str); System.out.println(ten); }
なんかOOPとは、、とか考え出すと原理主義的になるので雰囲気で良いと思うんですけどね、個人的には。我々は雰囲気でコードを書いている。
companion objectとobjectとは
companion objectとobjectはシングルトンパターンのクラスと思ってもらえれば大体オッケーです。companion objectは制約付きのobjectみたいな感じです。
気になる方はcomapnion objectやobjectを書いてみてIntelliJ IDEAかAndroid Studioで出来たクラスバイトコードをデコンパイルして見て下さい。
参考:
「Show Kotlin Bytecode」でKotlinを理解する
まとめ
- Kotlinにはstaticフィールドはない。
- staticフィールドはなくてシングルトンなんだけどstaticフィールドのようなアクセスが出来る
- そういう風にしてるのは言語デザイン的にstatic要らんやろってなってるから
- でもバイトコード上でstaticフィールド求められるときはあるからJvmFieldというものを提供している
宿題
@yy_yank なぜstatic memberよりもcompanion objectの方がいいのか、モジュラリティについての言及がほしかったです!
— がくぞ (@gakuzzzz) 2017年3月25日
@backpaper0 @yy_yank 例えばJavaでclass Aとclass Bに共通のstaticメソッドをDryに書きたいと思ったらどうなるでしょう?それに対してKotlinでは?
— がくぞ (@gakuzzzz) 2017年3月25日
@gakuzzzz @backpaper0 うーん、うーん、、
— やんくです (@yy_yank) 2017年3月25日
Javaだと共通な処理を持ったCを継承したAとBがCの持つstaticメソッドにアクセスできるけどKotlinだと出来ないとかそんな感じですか?
@yy_yank @backpaper0 逆です逆です。Javaだとstatic memberの継承ができないけどKotlinだとできるという話です
— がくぞ (@gakuzzzz) 2017年3月25日
逆にstaticが特殊であるという話
@gakuzzzz @yy_yank @backpaper0 関係するようなずれるような話をしますが、staticが無いのはなんで?というのは疑問の立て方としては逆だと思うのです。より一般的な見地からは、何故Javaにはstaticが必要であるのか?という疑問になるのではと。
— 水島宏太(ゆる糖質制限) (@kmizu) 2017年3月25日
@gakuzzzz @yy_yank @backpaper0 歴史的にみても、staticなんちゃらはC++から継承した機構であって、オブジェクト指向言語に一般的なものでもないと思うのです。実際、staticメンバがあるオブジェクト指向言語の方が数としては少ないと思います。
— 水島宏太(ゆる糖質制限) (@kmizu) 2017年3月25日
0 件のコメント:
コメントを投稿