[Kotlin]クラスに可視性修飾子を設定する方法

今回はKotlinのクラス内に設定する可視性修飾子についてお話します。可視性修飾子によって、そのクラスの「カプセル化」を進めることができます。

これは「継承」や「ポリモーフィズム」と並んでオブジェクト指向プログラミングのキーワードであり、中でもカプセル化は非常に重要な概念です。

可視性修飾子の種類

まず始めに、可視性修飾子の種類を挙げておきましょう。Kotlinのクラスに設定できる可視性修飾子には4つの種類があります。

修飾子意味
public (デフォルト)プログラムのどこからでもアクセス可能
privateそのクラスの内側からのみアクセス可能
protectedそのクラスか、そのクラスを継承するクラスからのみアクセス可能
internal同じモジュールの内側からのみアクセス可能

この中で特にprotectedとinternalについては、文章では若干分かりにくいかと思うので、イメージしにくいという方は以下の図で確認してみてください。

public:

private:

protected:

internal:

可視性修飾子を設定する

それではこれまでに作ったクラスを使って、可視性修飾子を設定していきます。

class Player(val name: String, var age: Int){
    val job = "プロ野球選手"
    var batting: Int? = null
    var hits: Int? = null

    init{
        require(name.isNotEmpty()) {"名前を入力してください"}
    }

    constructor(name: String,
                age: Int,
                batting: Int,
                hits: Int):this(name,age){
        this.batting = batting
        this.hits = hits
    }
    fun calcAvg():String{
        val a = requireNotNull(batting)
        val b  = requireNotNull(hits)
        val ans = String.format("%.3f",b.toDouble() / a.toDouble())
        return "${ans[2]}割${ans[3]}分${ans[4]}厘"
    }
}

この時点では可視性修飾子は設定されておらず、インスタンスを生成することによって、他のファイルからでもそのプロパティやメソッドにアクセスすることができます。

fun main() {
    val yamada = Player("山田哲人",27,524,165)
    println(yamada.hits)
    println(yamada.calcAvg())
}
//165
//3割1分5厘

プロパティのhitsに可視性修飾子「private」を設定してみましょう。(メソッドに設定する場合も同じ要領でかまいません)

class Player(val name: String, var age: Int){
    ...
    private var hits: Int? = null
    ...
}

この状態でmain関数をもう一度実行するとエラーになります。

//エラー:(3, 20) Kotlin: Cannot access 'hits': it is private in 'Player'

hitsプロパティにはmainメソッドのファイルからはアクセスできなくなりました。それではこの状態で、hitsプロパティを使用するcalcAvgメソッドはどうでしょう?

println(yamada.calcAvg())     //3割1分5厘

calcAvgメソッドはprivateなプロパティを参照するメソッドにもかかわらず、使用することができます。hitsを定義しているクラス内部では、hitsに対するアクセスが許容されているためです。

このように可視性修飾子はプロパティやメソッドへのアクセスを制限し、開発者が意図しない呼び出しを抑制することによって、プログラムの安全性を高めます。いわゆる隠蔽化です。

コンストラクタを隠蔽する

この可視性修飾子、実はコンストラクタにも設定することが可能です。Playerクラスのプライマリコンストラクタに可視性修飾子を設定してみましょう。

class Player private constructor(val name: String, var age: Int){
    ...
}

「クラス名 可視性修飾子 constructor(…)」とすることで、このクラスのプライマリコンストラクタはクラス内部でしか呼び出せず、外部からインスタンスを生成することができなくなります。

ただし今回使用しているPlayerクラスの場合は、セカンダリコンストラクタが定義されているため、セカンダリコンストラクタを使用したインスタンス生成は行うことができます。
コンストラクタを複数設定している場合、外部からのインスタンス生成をコントロールするには、コンストラクタ毎に可視性修飾子を設定しておきましょう。

タイトルとURLをコピーしました