Javaのアクセスレベル (public, protected, パッケージプライベート, private)の使い分け

前回Javaの4つのアクセスレベルについて書きました。

今回はその4つのアクセスレベルをどう使い分ければ良いか書きたいと思います。

結論

要件を満たす中で、最小のアクセスレベルを選択する。

トップレベルのクラス

他のパッケージに公開する必要がある
→ public

他のパッケージに公開する必要がない

→ パッケージプライベート

クラスメンバ

他のパッケージに公開する必要がある

→ public, protected

他のパッケージに公開する必要がない

→ パッケージプライベート, private

基本方針

Effective Java には以下のように書かれています。

大まかなやり方は単純です。すなわち、各クラスやメンバーをできる限りアクセスできないようにすべきです。

基本的にはこの方針に従っていけば問題ありません。

各アクセスレベルを理解しておき、今実装しているクラスやメンバをどこまで公開する必要があるかを考えていきます。

public, protected vs パッケージプライベート, private

「public, protected」と「パッケージプライベート, private」の間にまず大きな違いがあります。

public, protected は異なるパッケージからアクセス可能、つまりAPIを公開することになります。

なので、トップレベルのクラス・インターフェースに関しては他のパッケージに公開する必要がある場合のみ public にし、必要がなければパッケージプライベートにすべきです。

メンバーに関しても、他のパッケージに公開する必要がある場合のみ public にします。

public vs protected

ここでも できる限りアクセスできないようにすべき という方針に従うのみです。

protected を使うと、別パッケージではそのクラスを継承したクラス内でしか見れなくなります。

そのため、継承せずに別パッケージから見る必要があれば public 、そうでなければprotected とします。

しかし、 protected を使う場合はパッケージプライベートや private ではダメなのか再考の余地があります。

先に述べた通り public や protected は API を公開することになるため、安易に実装を変えられなくなりますので、 protected を使わずともパッケージプライベートで要件を満たせるのであれば大きなリターンがあります。

Effective Java でも以下のように書かれています。

protected のメンバーの必要性は、比較的にまれであるべきです。

継承させて使うことを意図したクラスを公開するというのは決して多くないと思います。

パッケージプライベートvs private

この2つは基本的にクラスの公開APIに影響しません。

同一パッケージからそのクラスやクラスのメンバにアクセスする必要があればパッケージプライベートを使います。

一番分かりやすいのは、テストコードを書く時でしょう。

パッケージプライベートであれば、同一パッケージのtestからメソッドを呼び出すことができます。

その必要がなければprivateを使いましょう。

クラスの public の API を注意深く設計した後に、無意識に行うべきことは、他のすべてのメンバーを private にすることです。

まとめ

何も考えずに public にしてしまうのは楽ですが、その分大きな責任が伴います。

基本的には public なクラスのメンバは全て private にしてみて必要なら広げてみるというやり方を取れば、都度アクセスレベルを意識できそうですね。