こんばんは。
本棚がいっぱいになって困っています。わたしです。
今回はアクセス修飾子について見ていきます。
基本
アクセス修飾子は型および型のメンバーにつけることができます。
アクセス修飾子の種類は以下の通りです。
修飾子 | Java | C# |
---|---|---|
public | どこからでもアクセス可能 | どこからでもアクセス可能 |
protected | 同一パッケージまたは派生クラスから アクセス可能 |
派生クラスからアクセス可能 |
protected internal | - | 現在のアセンブリまたは派生クラスから アクセス可能 |
internal | - | 現在のアセンブリからアクセス可能 |
なし | 同一パッケージからアクセス可能(default) | クラスはinternal、メンバーはprivateと同じ扱い |
private | 自クラスからのみアクセス可能 | 自クラスからのみアクセス可能 |
※現在のアセンブリはコンパイルされたコードライブラリのこと(具体的にはEXEとDLL)
※privateはインタフェースとか列挙型ももちろん可
挙動が同じなのはpublicとprivateのみですね。
Javaの場合には「何もつけない」修飾子(defaul修飾子)が存在しているのに対して、
C#の場合には何もついていないときはinternalまたはprivate扱いということになっているので注意。
また、Javaがパッケージ単位でアクセス制限をしているのに対して、
C#がアセンブリ単位でアクセス制限をしているのもポイントです。
クラスのアクセス修飾子
アクセス修飾子を付ける対象によって、選択肢が異なることには注意が必要です。
ネストしていない(一番外側の)クラス
修飾子 | Java | C# |
---|---|---|
public | どこからでもアクセス可能 | どこからでもアクセス可能 |
internal | - | 現在のアセンブリからアクセス可能 |
なし | 同一パッケージからアクセス可能(default) | internalと同じ扱い |
Javaでは一番外側のpublicなクラスは一つの.javaファイルに一つしか定義できません。
また、ファイル名とpublicなクラスの名前は一致している必要があります。(インタフェースも同じ)
クラスのメンバー(変数とかメソッドとか)
修飾子 | Java | C# |
---|---|---|
public | どこからでもアクセス可能 | どこからでもアクセス可能 |
protected | 同一パッケージまたは派生クラスから アクセス可能 |
派生クラスからアクセス可能 |
protected internal | - | 現在のアセンブリまたは派生クラスから アクセス可能 |
internal | - | 現在のアセンブリからアクセス可能 |
なし | 同一パッケージからアクセス可能(default) | privateと同じ扱い |
private | 属するクラスまたは属するクラスの ネストクラスからのみアクセス可能 |
属するクラスまたは属するクラスの ネストクラスからのみアクセス可能 |
注意としてはネストクラスで外側のクラスの方が可視性が低い場合、外側のクラスの可視性に引っ張られます。
例えば、外側のクラスが修飾子なしでネストクラスがpublicだとすると、
外側のクラスが見えない場合にはネストクラスも見えません。当然といえば当然。
ネストしているクラス、インタフェース
メンバーと同じです。
インタフェースのアクセス修飾子
ネストしていない(一番外側の)インタフェース
修飾子 | Java | C# |
---|---|---|
public | どこからでもアクセス可能 | どこからでもアクセス可能 |
internal | - | 現在のアセンブリからアクセス可能 |
なし | 同一パッケージからアクセス可能(default) | internalと同じ扱い |
継承とかなんとか
クラスの継承の際に可視性を変更することができます。
Javaでは上げることも下げることもできます。
class Test { class A {} public class C extends A {} private class D extends A {} }
C#では上げることはできません。
class Test { class A {} // ダメ //public class C : A {} private class D : A {} }
また、Javaではメソッドをオーバーライドする際に可視性を変更することもできます。
上げることはできますが、下げることはできません。
class Test { abstract class A { protected abstract void method(); } // OK class B extends A { @Override public void method() {} } // ダメ // class C extends A { // @Override // private void method() {} // } }
C#では可視性の変更はできません。
class Test { abstract class A { protected abstract void method(); } // ダメ //class B : A //{ // public override void method() { } //} // ダメ //class C : A //{ // private override void method() { } //} }
少し余計な話をすると、Javaの場合は外側のクラスを継承して可視性を上げるとメンバを外から見ることができます。
ので、修飾子なしクラスにpublicなネストクラスを作ることに全く意味がないわけでもないことも・・・ない?
class A { public class B { } } public class C extends A { }
とした上で、
// A.B c = new A().new B(); Aが見つからないのでダメ C.B c = new C().new B(); // OK
みたいに参照できるわけですね。
まぁそんなことしないけど。
なんでもpublicにすればいいってもんじゃないんだぞ
ちゃんと考えると結構難しいアクセス修飾子ですが、
publicかprivateしかないプロジェクトなんて言うのも結構あったりしますよね。
かつて私のいたプロジェクトもprotectedやdefaultを使っているのが自分だけだったりしました。
フィールドは全部private、クラスは全部publicなんていうのはちょっとどうかと思います。