【第16回】勝手に変えられたくない...メンバへのアクセス制限
「クラス」について何度か触れてきましたが、
今回はその中でも重要な「メンバへのアクセス制限」について説明しましょう。
前提: 第9回、第10回のイメージがつかめている。
「メンバ」とは、”フィールド(属性)”と”メソッド”を称して「メンバ」と呼びます。
今回は”フィールド(属性)”について説明していきます。
...なにやら始めから「クラス」「メンバ」「アクセス制限」「フィールド」...っと
難しそうな言葉が並んでいますが、他の人が書いたプログラムを読む上でも必要な知識なので、
ここは「ふ~ん。そういうものね」くらいの認識でも最後まで読み進めて行きましょう。
フィールドは、使用用途によってアクセス制限(使用制限)を行えます。
まずは、「第10回複数のクラスを扱う」で使用したプログラムを入力・実行してみましょう。
public class AnotherClassSample { private String name; // (A) // コンストラクタ public AnotherClassSample() // (B) { System.out.println("AnotherClassSample Constructor!!"); // (C) name = "foo"; // (D) } // 名称設定 public void setName(String newName) { name = newName; // (E) } // 名称表示 public void printName() { System.out.println("My name is " + name + "."); // (F) } }
public class ClassSample { private String msg; // (1) public ClassSample() { System.out.println("Constructor Was Called."); // (2) } public void setMessage(String inMsg) { msg = inMsg; // (3) } public void printMessage() { System.out.println("message:" + msg); // (4) } public static void main(String[] args) { ClassSample classSample; // (5) classSample = new ClassSample(); // (6) classSample.setMessage("Hello Java World!"); // (7) classSample.printMessage(); // (8) AnotherClassSample anotherClass = new AnotherClassSample(); // (9) anotherClass.printName(); // (10) anotherClass.setName("bar"); // (11) anotherClass.printName(); // (12) } }
コンパイル・実行結果は以下の通りです。
C:\work>javac ClassSample.java AnotherClassSample.java C:\work>java ClassSample Constructor Was Called. message:Hello Java World! AnotherClassSample Constructor!! My name is foo. My name is bar. C:\work>
1.private
ここで値の代入に着目してみましょう。
AnotherClassSampleクラスで値の代入を行っている(E)を見てみましょう。
「private String」で宣言されている「name」に対して代入を行っています。 これは、「name」がAnotherClassSampleクラスのprivateフィールド(またはprivate属性)である事を示します。
今までの講座では、メソッド内で宣言する「変数」を扱ってきましたね。
フィールドも変数の一種です。
何が違うのかと言うと、
・メソッド内で宣言される変数はメソッド内でのみ使用できる
・クラスのフィールドとして宣言した変数はクラス内、またはクラス外からの参照が可能。
(但し、アクセス制限による)
となります。
では、「private」は何をあらわすのでしょう。
これは「宣言されたクラス内でのみ参照が可能」である事をあらわします。
????...具体的に試してみる必要がありそうですね。
ClassSampleクラスは直接AnotherClassSampleクラスのフィールドにはアクセスせずに、
setNameメソッドを利用して値の代入を行っています。
ここで、AnotherClassSampleクラスのフィールドに直接代入を行うように書き換えてみましょう。
public static void main(String[] args) { ClassSample classSample; // (5) classSample = new ClassSample(); // (6) classSample.setMessage("Hello Java World!"); // (7) classSample.printMessage(); // (8) AnotherClassSample anotherClass = new AnotherClassSample(); // (9) anotherClass.printName(); // (10) anotherClass.setName("bar"); // (11) anotherClass.name = "change"; // (13) anotherClass.printName(); // (12) }
ClassSampleクラスのmainメソッドに(13)を追加して、コンパイルすると
C:\work>javac ClassSample.java ClassSample.java:32: name は AnotherClassSample で private アクセスされます。 anotherClass.name = "change"; // (13) ^ エラー 1 個 C:\work>
ご覧の通り、アクセスを制限されているために、エラーとなってしまいました。
2.public
では、AnotherClassSampleクラスのフィールド「name」を「public」で宣言してみましょう。
public class AnotherClassSample { // private String name; // (A) public String name; // (A') // コンストラクタ public AnotherClassSample() // (B) { System.out.println("AnotherClassSample Constructor!!"); // (C) name = "foo"; // (D) } // 名称設定 public void setName(String newName) { name = newName; // (E) } // 名称表示 public void printName() { System.out.println("My name is " + name + "."); // (F) } }
コンパイルすると...。
C:\work>javac ClassSample.java AnotherClassSample.java C:\work>
早速、実行してみましょう。
C:\work>java ClassSample Constructor Was Called. message:Hello Java World! AnotherClassSample Constructor!! My name is foo. My name is change. C:\work>
今度は成功しました。 もう、おわかりですね。
「public」と宣言れば、宣言したクラスの外部からも参照が可能となります。
では、どうしてこんなアクセス制限があるのでしょう。
「全部publicで良いじゃんっ!」と思う人も少なくないでしょう。
これは、「クラス内で宣言されているフィールドは、宣言したクラスが責任をもつ」ために
必要な事なのです。
例えば、以下のプログラムを見て下さい。
// 人間クラス public class Man { private String personalName; // 登録されている名前 // コンストラクタ(名前を指定) public Man(String name) { // 指定のnameを名前として登録する personalName = name; } // 名前取得メソッド public String getName() { return personalName; // 登録されている名前を返す } }
この「人間クラス」は生成に「名前」を設定します。
(「コンストラクタ」はクラス生成時に実行されるもの)
getNameメソッドがあるため、「名前」を確認する事はできます(名前を呼べば答えてもらえる)。
privateで宣言されたフィールドであるために他からの更新は行えませんし、
更新するメソッドもありません(そもそも、「名前」を勝手に変えられてたまるか!)。
そうです。他のクラスから変更させない為には「private」で宣言する必要があるのです。
どうですか?イメージできましたか?
ここでは、 “他のクラスで勝手に値を変えたくないから「private」”と覚えておきましょう。
「private」「public」の他にも、「protected」がありますが、これはもっと後で説明する事にしましょう。
1.フィールドとして宣言した変数はクラス内で参照が可能となる
2.フィールドは宣言の方法によりアクセス制限が行える
3.クラス内で宣言されているフィールドは、宣言したクラスが責任をもつ
それでは、また次回にお会いしましょう。