13 パッケージについて理解する

【第13回】パッケージについて理解する

今回は、パッケージについての紹介です。
パッケージについて学ぶことで、既存のクラスを利用するための準備が整うことになります。

前提: 前回と同様に、複数クラスを利用する事にメリットを感じている

複数のクラスを作成していくうちに、クラスが煩雑になりがちです。
そこでパッケージを用いて整理する事を学びましょう。

パッケージとは何か

さて、パッケージとは一体何でしょうか?
パッケージとは、大雑把にいってしまえば、たくさんあるJavaのクラスを
分類するための仕組みのことです。

例えば、あるJavaのクラス(ここでは、MyClassという名前のクラスとしましょう)が
fooという名前のパッケージに属することを宣言する場合、MyClass.javaの先頭に、

package foo;

と記述します。これでクラスMyClassが、パッケージfooに属することを宣言したことになります。
逆に、異なるパッケージに属するクラスを使用したい場合、import文を使用して
異なるパッケージのクラスを使用することを宣言しなければなりません。
例えば、先ほど宣言したfooパッケージのMyClassを使用したい場合、
以下のようにしてインポート宣言を行います。

import foo.*;

1.オブジェクトとは?

ここまでの説明だけでは、面倒な手続きが余計に増えただけで、
なんだかあまりありがたくありませんね。
それでは、パッケージを利用することのメリットとは何でしょう?

簡潔にまとめると、パッケージを利用することで以下のようなメリットを得ることができます。

1. 関連するクラスをまとめることで、クラスの分類・整理がしやすくなる。
2. 名前空間を利用することで、クラス名の衝突を防ぐことが出来る。

まだちょっとわかりにくいですね。もう少しかみ砕いて説明しましょう。

2.クラスの分類・整理

実際の開発では、数十、数百単位のクラスを作成することも希ではありません。
原則として同じ名前のクラスを2つ以上作ることはできませんが、こうたくさんクラスがあっては、
同じ名前のクラスがあるかどうかを考えるだけでも嫌になりますよね。
この問題もパッケージを使用することで解決されます。
異なるパッケージであれば、同じ名前のクラスがあっても許されるからです。

この仕組みは複数メンバーで共同開発を行う場合も有効です。
Aさんの担当する function-a パッケージと、Bさんの担当するfunction-b パッケージというように
パッケージを分けていれば、AさんとBさんが、State という同じ名前のクラスを作っても大丈夫です。
AさんとBさんは、それぞれ自分の担当するパッケージの中でクラス名が重複しないように
気をつければよいのです。

パッケージ名を決める際には、他に誰も使っていないパッケージ名にするために、
インターネットのドメイン名を逆順にしたものを利用するのが一般的です。
(インターネットのドメイン名は世界中で唯一だからです)

Acroquestの場合は、ドメイン名が acroquest.co.jp なので、

jp.co.acroquest.project1
jp.co.acroquest.project2

など、jp.co.acroquest で始まるパッケージ名を使用します。

この慣例に従っていれば、パッケージ名が衝突する可能性はまずありません。

3.パッケージを使うときのルール

このあと、実際にパッケージを利用したサンプルプログラムを作成しますが、
一つだけ守らなければならないルールがあります。

パッケージを利用したクラスファイルは、
パッケージ名と同じ名前のフォルダに置かれなければならない。

Javaのクラス名とファイル名を同じ名前にしなければならないのに似ていますね。
例えば、mypackage というパッケージのクラス、MyAp は、mypackage という名前の
フォルダに置かなくてはいけません。クラスファイルのファイル名は、もちろん MyAp.class です。

また、mypackage.sub というパッケージを作る場合は、mypackageフォルダの下に
sub という名前のフォルダを作成して、パッケージの階層とフォルダの階層をあわせておく
必要があります。

このとき、mypackage フォルダ自体はどこに置かれていても構いませんが、
mypackage が置かれているフォルダにクラスパスを通しておく必要があります。
(これについては、あとでもう少し詳しく説明しましょう)

ちょっと面倒そうですか? でも、そんなに難しいことはありません。
このようにパッケージ階層とフォルダ階層をあわせておくことで、
ソースファイルそのものもフォルダに分けて管理することができるので、
あとあと整理しやすいのです。

4.パッケージの実例

では、実際にパッケージを利用してみることにしましょう。
リスト1~3のように、MyMain、MyAp、MySub の3つのクラスを作成してください。

リスト1 – MyMain.java

import mypackage.MyAp;
import mypackage.sub.SubAp;

public class MyMain
{
    public static void main(String[] args)
    {
        MyAp ap = new MyAp();
        SubAp subap = new SubAp();
        ap.print();
        subap.print();
    }
}

リスト2 – MyAp.java

package mypackage;

public class MyAp
{
    public MyAp()
    {
        System.out.println("Invoke mypackage.MyAp!");
    }

    public void print()
    {
        System.out.println("mypackage.MyAp.print()!");
    }
}

リスト3 – SubAp.java

package mypackage.sub;

public class SubAp
{
    public SubAp()
    {
        System.out.println("Invoke mypackage.sub.SubAp!");
    }

    public void print()
    {
        System.out.println("mypackage.sub.SubAp.print()!");
    }
}

各ソースファイルは先ほど説明したルールに従ったフォルダに保存します。
MyMain.javaはいつものフォルダ(C:\work)に、MyAp.javaはmypackageパッケージのクラスなので
mypackageというフォルダに保存します。SubAp.java は、mypackage.subパッケージなので
mypackage の下に sub という名前のフォルダを作成してそこに保存します。

C:\
  +-\work
    +-MyMain.java
    +-\mypackage
      +-MyAp.java
      +-\sub
        +-SubAp.java

ソースファイルの準備ができたらコンパイルしてみましょう。
ソースファイルが複数のフォルダにある場合には、mainを含むプログラムをコンパイルする、
もしくは、以下のようにしてそれぞれのフォルダでコンパイルする必要があります。
(今回は地道にコンパイルしてみましょうか)

C:\work>cd mypackage\sub

C:\work\mypackage\sub>javac SubAp.java

C:\work\mypackage\sub>cd ..\

C:\work\mypackage>javac MyAp.java

C:\work\mypackage>cd ..\

C:\work>javac MyMain.java

C:\work>

コンパイルできましたか?
以下のように、それぞれのフォルダにクラスファイルができていればOKです。

C:\
  +-\work
    +-MyMain.class
    +-\mypackage
      +-MyAp.class
      +-\sub
        +-SubAp.class

それでは、実行してみましょう。
実行するクラス名は勿論、main メソッドがあるMyMain クラスですね。

C:\work>java MyMain
Invoke mypackage.MyAp!
Invoke mypackage.sub.SubAp!
mypackage.MyAp.print()!
mypackage.sub.SubAp.print()!

C:\work>

うまくいきましたか?

MyMain クラスのmainメソッドの中を見てみましょう。最初に MyAp クラスをnew しています。
クラスをnewするときは、通常同じパッケージの中から探します。
しかし、MyApクラスはMyMainクラスとは異なるパッケージ(つまり同じフォルダにはない)なので
importする必要があります。

import mypackage.MyAp;

このimport文から、Javaは mypackageフォルダ配下に存在する MyAp.class を見つけることが
できるのです。

次に、SubAp クラスを new しています。
SubApクラスもMyAPクラスと同様に、import 文を記述することで、
mypackage.sub に存在する SubAp クラスを使用することをJavaに教えているのです。
また、package内の複数クラスを利用する場合には、

import mypackage.*;
import mypackage.sub.*;

と記述する事もできます。

~ まとめ ~

1.「パッケージとは何か」がイメージできた
2.パッケージを使用する事により、クラスを整理できる事がわかった
3.パッケージ名とフォルダ名をあわせる必要がある事がわかった
4.パッケージは階層に作成できる事がわかった

さて、今回の講義はここまでです。いろいろと面倒(そう)なことは増えますが、
パッケージはある程度以上の大きさのプログラムを作るときには、非常に有効な手段です。
皆さんもパッケージを活用して、見通しの良いクラス構成を心がけていきましょう。

→ 次へ(第14回:例外に対処する)