先日、GithubでKotlinのコードを眺めていたら以下のような記述を見かけました。
package hoge.huga
class Hoge {
...
}
private const val HUGA = "Huga"
定数がパッケージの宣言と同じレベルに宣言されています。
初めてみた書き方だったので色々調べてみました。
#トップレベル宣言 (Top-level Declarations)
Javaではトップレベルに宣言できるのはクラスのみですが、Kotlinではクラスの他に
・関数
・プロパティ
・型エイリアス
なども宣言することができます。
上記のように、パッケージのトップレベル(パッケージレベルとも)に関数やプロパティを定義することを**トップレベル宣言(Top-level Declarations)**といいます。
トップレベルに宣言されたものは、クラスインスタンスを経由せずに使用することができます。
Companion Objectとの使い分け
ところでKotlinにはstatic修飾子がありません。
代わりにKotlinではトップレベルに宣言するほかに、companion object
を使用することが代替手段として挙げられます。
両者の大きな違いとして、トップレベル関数からはクラスのprivateメンバにアクセスすることができません。
そのため、ファクトリーメソッドのようにクラス内部にアクセスしたい場合には、companion objectを使用します。
バイトコードとしての差など、より詳しい違いについては、こちらの記事が非常に参考になりました。
おまけ:Javaから見たトップレベル宣言
KotlinとJavaは相互利用することが可能ですが、以下のように.ktファイルに宣言された関数をJavaから呼び出す場合、どうなるのでしょうか。
package com.hoge
fun printHoge() {
println("Hoge")
}
Javaにおいて全てのメソッドはクラスに属していなければならないため、Hoge.kt
というファイル名から自動的に生成されたHogeKt
クラスを介して呼び出す必要があるようです。
import com.hoge.HogeKt;
public class Huga {
public static void main(String args[]) {
HogeKt.printHoge();
}
}
ファイル名から自動生成されるクラスにはJvmNameアノテーション
を使用して任意の名前を指定することができます。
@file:JvmName("Hoge")
package com.hoge
fun printHoge() {
println("Hoge")
}
import com.hoge.Hoge;
public class Huga {
public static void main(String args[]) {
Hoge.printHoge();
}
}