ファイル分割およびアクセス修飾子 (Java)
[履歴] [最終更新] (2013/08/12 02:27:19)

概要

一つのファイルあたり、publicで修飾できるclassまたはinterfaceは最大一つまでです。また、publicで修飾した場合、ファイル名は「クラスまたはインターフェース名.java」とする必要があります。あるファイル群を特定のディレクトリ、例えばmypackageディレクトリに移動させ、各ファイルの先頭付近で「package mypackage;」と宣言すると、それらファイル群はパッケージとしてJavaに認識されます。あるパッケージに属するクラスは、パッケージに属さないクラスからimportすることによって利用できるようになります。利用できる範囲は、アクセス修飾子に依存します。

ディレクトリ構成

本ページのサンプルファイルのディレクトリ構成は以下のようになっているとします。

$ tree .
.
|-- mypackage
|   |-- C1.java   <== クラス
|   |-- C2.java   <== クラス
|   `-- I1.java   <== インターフェース
`-- sample.java   <== いわゆるメイン

サンプルコード

sample.java

// C++のusing namespaceのようなもの
// C1.java,C2.java,I1.javaでpublicされている
// classまたはinterfaceを短い名前で利用できるようにする
import mypackage.*;

class Sample {
    public static void main(String args[]) {
        C1 c1 = new C1();
        // C1 c1 = new mypackage.C1();  //importしていない場合、このように長い名前でのアクセスが必須


        // インターフェース名で型を指定可能
        // ただしアクセスできるのはI1.javaで定義するように要請したもののみであり
        // C2.javaで独自に追加されたものはアクセスできない
        I1 c2 = new C2(128);
        System.out.println(c2.constVal);

        // C2 c2 = new C2(128);        // こうすると
        // System.out.println(c2.val); // これが可能

        c1.display();
        c2.display();
    }
}

C1.java

package mypackage;

public class C1 {
    public void display() { System.out.println("class C1"); }
}

I1.java

package mypackage;

// public: 任意のクラスからアクセス可能
// 省略時: パッケージmypackageからのみアクセス可能
public interface I1 {

    // インターフェースの変数定義におけるアクセス修飾子は指定しない。この場合、
    // 「public static final」つまり、任意のクラスからアクセスできるクラス定数となる
    int constVal = 1024;

    // インターフェースのメソッド定義におけるアクセス修飾子は
    // 「public abstract」とする。指定しない場合「public abstract」となるため
    // 省略してもよい。
    public abstract void display();
}

C2.java

package mypackage;

// public: パッケージmypackageに属さないクラスからもクラスC2を利用できるようにする
// final: クラスC2を継承できないようにする
// abstract: クラスC2をインスタンス化できないようにする (extendsで継承されることを意図する)
// 省略時: パッケージmypackageに属さないクラスからはクラスC2を利用できない
public class C2 implements I1 {// implements I1, I2 とカンマ区切りで複数指定可能

    // private: クラスC2外からアクセスできなくなる
    // protected: 他のパッケージ (ただしサブクラスは除く) からアクセスできなくなる
    // public: 任意のクラスからアクセス可能
    // static: クラス変数化する
    // final: 定数 (C/C++のconst) 化する。static finalという記述でクラス定数を設定可能
    // 省略時: 他のパッケージ (サブクラスを含む) からアクセスできなくなる
    public int val;

    // private: 他のクラスからnewできなくなる (使用用途例: Singleton)
    // protected: 他のパッケージ (ただしサブクラスは除く) からnewできなくなる
    // public: 任意のクラスからnewできる
    // 省略時: 他のパッケージ (サブクラスを含む) からnewできなくなる
    public C2(int val) {
        this.val = val;
    }

    // private: 他のクラスから呼び出せないメソッド
    // protected: 他のパッケージ (サブクラスは除く) からは呼び出せないメソッド
    // public: 任意のクラスから呼び出せるメソッド
    // static: クラスメソッド化
    // final: オーバーライドできないメソッド化
    // abstract: サブクラスで実装されることを意図する (クラス自身もabstractで修飾されている必要がある)
    // 省略時: 他のパッケージ (サブクラスを含む) から呼び出せなくなる
    public void display() { System.out.println("class C2"); }
}

実行例

$ javac mypackage/*.java sample.java && java Sample
1024
class C1
class C2

パッケージ (ディレクトリ) の場所

カレントディレクトリまたは環境変数$CLASSPATHで指定されたディレクトリであればimportできます。

関連ページ
    概要 こちらのページでは、ある処理フローの大まかな流れをAbstractClassに記述しておき、実際の具体的な処理はConcreteClassに記述するという、システムのフレームワークを実装する場合に有用なTemplate Methodパターンを紹介しました。このTemplate Methodを用いて、インスタンスの生成処理のフレームワークを実装する場合を特にFactory Methodパター