Kotlin の companion object について調べてみた
以前 Kotlin のオブジェクトの初期化について書きましたが、その際いろいろ調べているうちに companion object なるものに出会っていました。全然分からなかったので、調べたことをメモします。
何はともあれ公式ドキュメント ↓
これ以降はそれをベースにしたものになります。
Companion objects allow you to define class-level functions and properties. This makes it easy to create factory methods, hold constants, and access shared utilities.
コンパニオンオブジェクトを使用すると、クラスレベルの関数とプロパティを定義できます。これにより、ファクトリーメソッドの作成、定数の保持、共有ユーティリティへのアクセスが容易になります、とのこと。
class Employee(val id: Int, nickname: String) {
var nickname: String = nickname
private set // セッターの可視性を private に設定
companion object Factory {
fun create(id: Int, nickname: String): Employee = Employee(id, nickname)
}
fun updateNickname(newNickname: String) {
this.nickname = newNickname
}
}
fun main() {
// クラス名を修飾子として使用するだけで companion object のメンバーを呼び出すことができる。
val momotaro = Employee.create(10, "Momotaro")
println(momotaro.nickname)
}
上の companion object 名は省略可能なので
companion object Factory {
これは
companion object {
こう書ける。
そうなると、名前は何のために付けるんだろ?意図を明確にするためとか?かな。
class 名はそのクラスの companion object の参照になる
fun main() {
// Employee クラスは上と同じためここでは省略。
// `Employee` は companion object の参照になる。
val employee = Employee
val jiro = employee.create(11, "Jiro")
println(jiro.nickname)
}
ちなみに companion object を実装せずにクラス名での参照をするとコンパイルエラーになる。
class Emp {
}
fun main() {
// コンパイルできない: Classifier 'class Emp : Any' does not have a companion object, so it cannot be used as an expression.
val emp = Emp
}
Although members of companion objects in Kotlin look like static members from other languages, they are actually instance members of the companion object, meaning they belong to the object itself. This allows companion objects to implement interfaces:
companion object のメンバーは他の言語の static メンバーのように見えるけど、実際はそのオブジェクトに属する。なのでインターフェースを実装できる、とのこと。
interface Factory<T> {
fun create(id: Int, nickname: String): T
}
class Employee(val id: Int, nickname: String) {
var nickname: String = nickname
private set // セッターの可視性を private に設定
// Factory interface を実装した companion object
companion object : Factory<Employee> {
override fun create(id: Int, nickname: String): Employee = Employee(id, nickname)
}
fun updateNickname(newNickname: String) {
this.nickname = newNickname
}
}
fun main() {
val employee: Factory<Employee> = Employee
val jiro = employee.create(11, "Jiro")
println(jiro.nickname)
}
However, on the JVM, you can have members of companion objects generated as real static methods and fields if you use the @JvmStatic annotation.
JVMでは、@JvmStatic
アノテーションを使用することで、companion object のメンバーを真の static メソッドおよびフィールドとして生成できます。詳細については、ここを参照とのこと。
ここは必要になったときに調べて理解しよう。
おしまい。
Discussion