【第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.クラス内で宣言されているフィールドは、宣言したクラスが責任をもつ
それでは、また次回にお会いしましょう。