再利用性の高いクラス作成に重要な“アクセス制御”【改訂版】Eclipseではじめるプログラミング(14)(2/3 ページ)

» 2010年01月28日 00時00分 公開
[小山博史株式会社ガリレオ]

ドキュメントだけでは自由にコーディングできる

 しかし、メソッドを使うようにドキュメントへ書いておいても、それだけではAppを下記のようにコーディングしてしまう人は必ず出てきてしまいます。UserInfoManagerのuserInfoArrayフィールドは、特にアクセス制御されていないため、Appが直接アクセスして操作できてしまうからです。ドキュメントで説明をするだけでは、不十分なのです。

package sample14.app3a;
class App {
    public static void main(String[] args) {
        UserInfo u = new UserInfo();
        u.name = "taro";
        u.eMail = u.name + "@example.jp";
        UserInfoManager manager = new UserInfoManager();
        manager.userInfoArray[0] = u;
        System.out.println(manager.userInfoArray[0].name);
        System.out.println(manager.userInfoArray[0].eMail);
    }
}
sample14/app3a/App.java(sample14.app3a.UserInfoManager実装依存版)

 このように、ほかのクラスからアクセスできるようにコーディングされてしまうと、あるクラス内のデータ構造を変更することが必要になったときに、影響が出てしまいます。これを防ぐ仕組みとして、Javaでは「public」「protected」「private」といったキーワードが用意されています。

Javaのアクセス修飾子は、3種類

 public、protected、privateは、クラス宣言、インターフェイス宣言、メンバ(フィールド、メソッド)宣言時に指定できます。これらを使うことにより、ほかのクラスやオブジェクトからフィールドにアクセスできるようにしたり、制限したり、といったことができます。

  • public
    publicキーワード付きのメンバは、メンバが定義されているクラスにアクセスできるクラスからアクセス可能
  • protected
    protectedキーワード付きのメンバは、そのクラスとサブクラスからアクセス可能。また、同じパッケージにあるクラスからもアクセス可能
  • private
    privateキーワード付きのメンバは、そのクラスからのみアクセス可能
  • アクセス修飾子なし
    public、protected、privateのいずれも付けていないメンバは、そのクラスと同じパッケージにあるクラスからのみアクセス可能

 クラス自身にも、アクセス修飾子を付けられます。クラスの場合は、publicを付けるか、付けないか、といった選択が基本です。publicを付けたクラスは、ほかのクラスからアクセスできます。

 また、このクラスから生成されたオブジェクトについても、同様にアクセスできます。付いていない場合は、同じパッケージにあるクラス以外のクラスからはアクセスができなくなります。

コラム 「Javaには“ネストされたクラス”ってのもあります」

クラス自身に付けるアクセス修飾子について補足しておきます。まだ説明していませんが、「ネストされたクラス」というものがJavaにはあります。「ネストされたクラス」では、protected、privateを付けることもできます。ネストされたクラスについては、別途紹介する予定です。


アクセス修飾子でクラス依存を解決するには

 アクセス修飾子がどういうものか知ったところで、「UserInfoManagerクラスの問題を解決するには、どうすればいいのか」を考えてみましょう。

 このクラスは同一パッケージに含まれないクラスからも利用できるように、publicとします。userInfoArrayフィールドへほかのクラスが直接アクセスできないようにするためには、privateを使います。すべてのメソッドは、ほかのクラスから利用可能にするため、publicを付けることにします。

 まとめたのが、次のコードです。

package sample14.app4;
public class UserInfoManager {
    private java.util.List userInfoArray = new java.util.ArrayList();
  
    public void add(UserInfo userInfo) {
        userInfoArray.add(userInfo);
    }
    public UserInfo get(int id) {
        return (UserInfo)userInfoArray.get(id);
    }
    public String getUserName(int id) {
        return get(id).name;
    }
    public String getUserEmail(int id) {
        return get(id).eMail;
    }
}
sample14/app4/UserInfoManager.java

 次のようなクラスを作り、コメント部を有効にすると、エラーになりアクセス制御がきちんとできていることが分かります。privateなフィールドへは、ほかのクラスからはアクセスができません。

 また、アクセス修飾子指定がないクラスは、ほかのパッケージのクラスからはアクセスできません。

package sample14.app4;
class App {
    public static void main(String[] args) {
        UserInfo u = new UserInfo();
        u.name = "taro";
        u.eMail = u.name + "@example.jp";
        UserInfoManager manager = new UserInfoManager();
        manager.add(u);
        System.out.println(manager.getUserName(0));
        System.out.println(manager.getUserEmail(0));
        // privateなフィールドへはアクセスできない
        //manager.userInfoArray.add(u);
        //System.out.println(manager.userInfoArray.get(0).name);
        //System.out.println(manager.userInfoArray.get(0).eMail);
        // アクセス修飾子指定がないクラスへはアクセスできない
        //sample14.app1.UserInfo u1 = new sample14.app1.UserInfo();
    }
}
sample14/app4/App.java

 ここまでの話で、フィールドをprivateにしておけば、クラス内のデータ構造を変更するような大きな実装変更があっても、ほかのプログラムへの影響を限定的にできることが理解できたでしょうか。

 今回までの連載では、publicはおまじないとして付けてもらうことがありましたが、今後は正しく意味を理解して使うようにしましょう。

アクセサメソッド「getter」「setter」とは

 フィールドは基本的にprivateとして非公開にするのが安全ですが、ほかのクラスがフィールド値を操作できた方が便利な場合もあります。その場合は、直接フィールドにアクセスさせるのではなく、専用メソッドを用意します。これは、「アクセサメソッド(accessor method)」と呼ばれます。

Eclipseだとアクセサメソッド作成が簡単

 Eclipseでは、アクセサメソッドを簡単に用意できるようになっています。アクセサメソッドは、フィールドの値をgetしたりsetしたりするために使うものなので、「getter」「setter」と呼ばれることもあり、メソッド名は「get」「set」で始まります。

 ただし、フィールドの型がbooleanの場合は、getに対応するメソッド名が「is」で始まります。

 UserInfoについて、アクセサメソッドを作成してみましょう。まず、次のクラスを作成します。

package sample14.app5;
public class UserInfo {
    private String name;
    private String eMail;
    private boolean member;
}
sample14/app5/UserInfo.java

 Eclipseでは、下記の手順でアクセサメソッドを簡単に作成できます。

  1. sample14.app5パッケージのUserInfo.javaをマウスで指定
  2. 右ボタンをクリックしてメニューを表示
  3. [ソース]→[GetterおよびSetterの生成]をクリック(図1)
  4. [GetterおよびSetterの生成]ダイアログで、フィールド「name」「eMail」「member」について、チェックボックスをチェック(図2)
  5. [OK]をクリック
図1 Eclipseでコンストラクタを自動作成 図1 クラスを選んで右クリックでメニューを出す
図2 [GetterおよびSetterの生成]ダイアログ 図2 [GetterおよびSetterの生成]ダイアログ

 次ページでは、生成されたアクセサメソッドがソースコードではどうなっているのかを確認し、最後にprotected宣言について、解説します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。