アクセス制御
アクセス修飾子
前回は、パッケージについて説明しました
パッケージを明示的に指定することで、そのクラス郡は不要なアクセスができなくなります
この機能によって、同一のディレクトリでも数十人の共同開発による名前の衝突などを避けられます
しかし、パッケージ化されたクラス郡は他のパッケージからではアクセスできなくなりました
今回は、他のパッケージからのアクセス方法について学びましょう
他のパッケージからのクラスへのアクセスは、クラス側が他のパッケージからのアクセスを許可していなければなりません
あらゆる class interface はデフォルトでアクセスを拒否します
他のパッケージからアクセスすることを想定したクラスには、明示的にアクセスを許可する必要があるのです
全てのクラスへの無条件のアクセスを許可するには public 修飾子を指定します
そうです、いまだに説明されていなかったmain()メソッドで使われていたアレです
public class clsName {...
上がクラスでの宣言、下がインターフェイスでの宣言です
clsNameはクラス名、intfはインターフェイス名を指定してください
このような、アクセス修飾子はクラス、インターフェイス、
メソッド、コンストラクタ、メンバ変数に指定できます
publicは、全てのクラスに対してアクセスを許可します
つまり、別パッケージも同様にアクセスすることができるのです
ただし別パッケージからのアクセスは完全修飾クラス名で指定することを忘れないでください
また、public 修飾子を持つクラスを宣言する場合
ソースファイルの名前を public クラスと同じ名前にしなければなりません
例えば public class Kitty { } を宣言する場合、ファイル名は Kitty.java です
//intf.java
package pak;
public interface intf {
String name = "kitty on your lap";
}
// pkcls.java
package pak;
public class pkcls {
public static void write(String str) {
System.out.println(str);
}
}
//test.java
class test extends pak.pkcls implements pak.intf {
public static void main(String args[]) {
pak.pkcls.write(pak.intf.name);
}
}
インターフェイスのメソッドや変数は、デフォルトでpublicなので指定する必要はありません
パッケージ pak に対して、デフォルトパッケージのtestクラスからアクセスしています
パッケージは、インターフェイスもクラスもpublicなので別々に用意します
では、逆に明示的に他のクラスからのアクセスを拒否するにはどうするのでしょう
その場合はprivateを使用します
書式や利用方法は全てpublicと同じです
privateは、同一クラス内メソッド以外のアクセスを全て拒みます
同一パッケージ、サブクラスからのアクセスも許されません
class NADESICO {
private String name;
private String fool;
void write() {
System.out.println(this.name + "\n" + this.fool);
}
NADESICO(String name , String fool) {
this.name = name;
this.fool = fool;
}
}
class test {
public static void main(String args[]) {
NADESICO rury = new NADESICO("星野ルリ" , "JAVAばっか…");
rury.write();
//System.out.println(rury.name); //<-これはエラーできない
}
}
NADESICOクラスのメンバ変数はprivateです
これらの変数にアクセスできるのは NADESICO クラスのメソッドだけです
private修飾子を利用することで、データの隠蔽ができます
不用意に変更したくないメンバ変数や、特定の場合のみに実行するメソッドに有効です
ただし、他のクラスから実行するためのインターフェイスとなるメソッドが必要です
NADISICOクラスの場合は、write()メソッドとNADESICOコンストラクタが
main()メソッドからprivateメンバ変数にアクセスする手段(インターフェイスメソッド)になっています
最後に、他のパッケージからのアクセスは許可しないがサブクラスの場合は許可したい場合があります
同一クラス、同一パッケージ、そしてサブクラスからのアクセスを許可するということです
このようなケースはprotected修正子を使用します
protectedは、他のパッケージで何の関係もないクラスからのアクセスを拒否します
書式や利用方法は、やはりpublicやprivateと同様です
// pkcls.java
package pak;
public class pkcls {
protected static void write() {
System.out.println("kitty on your lap");
}
}
//test.java
class sub_class extends pak.pkcls {
sub_class() {
pak.pkcls.write();
}
}
class test {
public static void main(String args[]) {
sub_class obj = new sub_class();
}
}
sub_classはpkclsを拡張していますが、パッケージが違うのでpkclsとの関連性はありません
write()メンバがデフォルト、またはprivateであればたとえサブクラスでもアクセス不能です
しかし、protected指定されているためパッケージが違ってもサブクラスの場合のみアクセスが許可されます
Java言語のアクセス修飾子は以上です
protectedはC++のprotectedとは若干違います
Java言語のprotectedは、このクラスとサブクラスと同一パッケージからのアクセスを許可します
C++では、このクラスとサブクラスのアクセス許可という意味でした
また、C++のFriendは存在しません
privateはprivateなんだから、privateなんだってことです???
| public | protected | デフォルト | private
|
---|
同一クラス | ○ | ○ | ○ | ○
|
---|
同一パッケージ | ○ | ○ | ○ | ×
|
---|
サブクラス | ○ | ○ | × | ×
|
---|
無関係 | ○ | × | × | ×
|
---|
完全限定名を省略する
別パッケージへアクセスするには完全限定名でアクセスしなければいけませんでした
これまでのような短いプログラムであれば、それでも苦になりません
しかし、構造化された長い完全限定名を何度もプログラム内で書くのは御免ですね
そこでimportステートメントを使用します
アプレットの作成を試みた方であれば、importを見たことがあると思います
import pak.fileName;
import pak.*;
pakにはパッケージ名を指定します。構造化されていれば、その文パッケージを記述します
fileNameにはクラス名、もしくはインターフェイス名を指定します
最初の書式は完全限定名を指定するものです
そのクラス、もしくはインターフェイスのみに有効です
後者は、指定されたパッケージの内容全てに有効です
importで指定すれば、そのファイル内ではもう完全限定名を指定する必要はありません
同一のファイル内のように、短い名前で指定することができます
// pkcls.java
package pak;
public class pkcls {
protected String str = "kitty on your lap";
protected static void write(String str) {
System.out.println(str);
}
}
//test.java
import pak.pkcls;
class sub_class extends pkcls {
sub_class() {
this.write(this.str);
}
}
class test {
public static void main(String args[]) {
sub_class obj = new sub_class();
}
}
sub_classでpkclsを拡張して使うため、importでpkclsを完全限定名で指定しています
これで、pkclsに関しては、同一ファイル内にあるかのように短い名前で指定できます
public
クラス、インターフェイス、メソッド、変数、コンストラクタの宣言で使用できます
パッケージ間を問わずに、あらゆるアクセスの許可を表します
publicクラスは、必ずファイル名と同じである必要があります
そうでない場合は、コンパイルエラーが発生します
protected
メソッド、コンストラクタ、変数の宣言で使用します
ただし、静的変数の宣言には使えません
同一クラス、同一パッケージ、サブクラスからのアクセスを許可します
private
メソッド、コンストラクタ、変数の宣言で使用します
ただし、静的変数の宣言には使えません
同一クラス内からのアクセスのみ許可し、データを隠蔽します
他のクラスからのアクセスは、たとえ同一クラス内からでも拒否されます
import
現在記述しているファイルで、短い名前でクラスを参照できるようになります
import文はひとつのファイルで複数指定できます
必ずファイルの先頭に記述します。ただしpackageステートメントがある場合はその後です