0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Kotlin】Objectの使い方とCompanion objects の特徴について

Last updated at Posted at 2025-05-01

はじめに

androidアプリを自作する中でKotlinについて学んだことを備忘として記事にします。
本記事ではCompanion objectsの特徴について記載します。

Object について

Companion objectsを説明する前に、まずはObjectの概念について説明します。
KotlinではObjectを使うことでクラスを定義し、さらにそのインスタンスを1ステップで作成できます。
これは、再利用可能なシングルトンインスタンスや1回限りのオブジェクトが必要な場合に便利です。

特徴

  • クラス定義からインスタンス定義までを1ステップで作成
  • 生成されるインスタンスはシングルトンインスタンスとなる

実行例: Kotlin Playground

// データプロバイダーを管理するためのシングルトンオブジェクトを宣言
object DataProviderManager {
    // プライベートな変数
    private val providers = mutableListOf<String>()

    // プロバイダーを登録
    fun registerDataProvider(provider: String) {
        providers.add(provider)
    }

    // 登録されたプロバイダーを取得
    val allDataProviders: Collection<String>
        get() = providers
}

// 使用例
fun main() {
    DataProviderManager.registerDataProvider("provider")
    print(DataProviderManager.allDataProviders)
}

// 実行結果
// [provider]

クラス内のObjectについて

クラス内でもObjectが定義できます。
Objectの内部変数はクラス内でも使用できます。
ただし、クラスのメンバー変数はObject内では使用できません。
Objectはクラスインスタンス生成前に利用できますが、クラスのメンバー変数は生成後にしか利用できないためです)

実行例: Kotlin Playground

class Food {
    
    fun cooking() {
        // Object内の変数はクラス内でアクセスできる
        println("cooking: ${BeefObject.GRAM}")
    }

    // シングルトンインスタンスとして生成される
    object BeefObject {
        const val GRAM = 200L
        private const val BEEF = "beef"

        fun getBeef(): String {
            return BEEF
        }
    }
}

// 使用例
fun main() {
    val food = Food()
    food.cooking()
    println(Food.BeefObject.GRAM)      // インスタンス生成済みのため、
    println(Food.BeefObject.getBeef()) // クラスをnewすることなく利用できる
}

// 実行結果
// cooking: 200
// 200
// beef

Companion objectsについて

クラス内で定義するObjectと基本的には同じですが、Companion objectsは1クラス1つだけしか定義できません。
用途として、KotlinにはJavaのstaticの概念が存在しないため、その代替としてCompanion objectsという同伴オブジェクトを使用して静的メンバーを定義することができます。

特徴

  • クラス内のObject定義と機能的には変わらない
  • 1クラスに1つのCompanion objectsしか定義できない制約がある
  • Javaのstatic変数のような静的な定数などを定義するのに利用できる

実行例: Kotlin Playground

class Food {
    
    fun cooking() {
        // Object内の変数に直接アクセスできる
        println("cooking: $GRAM")
    }

    // シングルトンインスタンスとして生成される
    companion object {
        const val GRAM = 300L
        private const val PORK = "pork"

        fun getPork(): String {
            return PORK
        }
    }
}

// 使用例
fun main() {
    val food = Food()
    food.cooking()
    println("With companion    : ${Food.Companion.GRAM}")
    println("With companion    : ${Food.Companion.getPork()}")
    println("Without companion : ${Food.GRAM}")      // Companion無しでも呼べる
    println("Without companion : ${Food.getPork()}") // Companion無しでも呼べる
}

// 実行結果
// cooking: 300
// With companion    : 300
// With companion    : pork
// Without companion : 300
// Without companion : pork

Object と Companion objects の違い

機能的には違いはなさそうですが、シングルトンオブジェクトが生成されるタイミングが異なります。

宣言 オブジェクト生成タイミング
Companion objects クラスロードされたときに生成される
クラス内Object宣言 自分自身が参照されたときに生成される

実行例: Kotlin Playground

class Food {
    companion object Beef {
        init { println("初期化 = Beef") }
        fun hello() = println("Beef!!")
    }

    object Pork {
        init { println("初期化 = Pork") }
        fun hello() = println("Pork!!")
    }
}

fun main() {
    println("------------- Food クラスのインスタンス化前")
    val obj = Food()
    println("------------- Food クラスのインスタンス化後")
    println("------------- Beef Companion objects の hello() 呼び出し")
    Food.Beef.hello()
    println("------------- Pork Object の hello() 呼び出し")
    Food.Pork.hello()
}

// 実行結果
// ------------- Food クラスのインスタンス化前
// 初期化 = Beef
// ------------- Food クラスのインスタンス化後
// ------------- Beef Companion objects の hello() 呼び出し
// Beef!!
// ------------- Pork Object の hello() 呼び出し
// 初期化 = Pork
// Pork!!

Companion objectsBeefインスタンスは、外側のクラスのFoodがインスタンス化されるときに生成されています。
一方で、オブジェクト宣言されたPorkオブジェクトはFood.Pork.hello()関数が呼び出された時点で初めて生成されます。

まとめ

単純にシングルトンインスタンスを生成したい場合はクラス内ではなく外側にObjectで定義しても良いかと思います。
Companion objectsはJavaのstaticの代替として利用する利用法がよさそうです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?