プログラミング応用a 第9回 『モジュール化その2 (パッケージ化とインポート、パッケージレベルでのアクセス制御)』 |
【パッケージ】
●クラスは,小さい『モジュール』であった。関連するクラスをまとめて,『パッケージ (package)』というより大きいモジュールにまとめることができる。
※パッケージは,ファイルシステム上ではフォルダとして表現されている(下図)。
※さらに,複数のパッケージをまとめて,より上位のパッケージを作ることができる。下位のパッケージをサブパッケージと呼ぶ。
例)下図は, Java に元から用意されているパッケージ(標準パッケージ)の階層の一部である。
・
java という最上位のパッケージのサブパッケージとして
awt, io, text, lang, math, net などがあることが分かる。
・
java のサブパッケージ awt には,さらにサブパッケージとして color, image, font などがあることが分かる。
■確認問題:上図に示した標準パッケージの一部の font パッケージの完全限定名は java.awt.font である。では, image パッケージの完全限定名は?
【クラスをパッケージへ編入する方法(package宣言)】
●あるクラスを特定のパッケージに編入したい場合は,ソースファイルの先頭で package 宣言を行う(下図)。
【パッケージとアクセス指定】
●あるパッケージのクラスを他のパッケージからも利用可能にするためには, クラス定義で public と指定してクラスを定義しなくてはならない。
(下図をクリックすると補助情報が表示されます)
表にまとめると次の様になる。
指定無しクラス | publicクラス | |
同一パッケージ内のクラスから | ○ | ○ |
別のパッケージ内のクラスから | × | ○ |
※つまり,publicクラスへはどこからでもアクセスできる
【メンバのアクセス指定ふたたび】
● メンバのアクセス特性を指定するとき, private 指定の他に,「指定無し」があったが,新たに「public指定」を紹介する。
privateメンバ | 指定無し(デフォルトアクセス)メンバ | publicメンバ | |
同一クラス内から | ○ | ○ | ○ |
同一パッケージ内のクラスから | × | ○ | ○ |
別のパッケージ内のクラスから | × | × | ○ |
※その他にprotectedというメンバアクセス指定があるがここでは省略する
※つまり,publicメンバはどこからでもアクセスできる
●図で見るprivateメンバ/デフォルトアクセスメンバ/publicメンバ
※つまり, public クラス(厳密には,publicクラスのpublicメンバ)はパッケージのインタフェイス部を構成する。
※それ以外(publicでないクラス,publicクラスのpublic以外のメンバ )は,パッケージの実装部を構成する。
手順2)Person.java(package宣言無しバージョン)とMeibo.java (package宣言無しバージョン) を,
上図のjinjiディレクトリに保存し,下図のように
・それぞれ1行目にpackage宣言を書き加え
・Personクラス自体とのPersonのコンストラクタをpublicに指定
・Meiboのコンストラクタと,put()メソッド,printAll()メソッドをpublicに指定して
保存し直せ。
今,状況は次のようになっている。
手順3)先ほどのMeiboTest01.java (import宣言無しバージョン) に,下図(1)のように1行目にimport宣言を付けて,
保存する。保存場所はどこでもいいが, Z:¥ooprog など,いつもjavaのプログラムを作成しているディレク
トリでよだろう。
次に,このMeiboTest01.javaをコンパイルするわけだが,このプログラムはimport宣言にあるように,
com.tuisjava.jinji パッケージのMeiboクラスを利用する。
前述したように,パッケージ化したクラスを利用するには,コンパイル時とプログラム実行時に,
・パッケージの起点となるディレクトリ(Fig.10の例ではmyclassesディレクトリ)の場所
を,javacコマンドや,javaコマンドに教えておく必要がある。(ちなみに,コンパイルやプログラムの実行時
に必要になるクラスの場所を示すファイルパス(file path name)のことを,クラスパス(class path)と呼ぶ。ここ
で指定するパッケージの起点となるディレクトリの場所もクラスパスの一種である)
パッケージの起点となるディレクトリの場所をjavac/javaコマンドに教える方法には,次の2つがある。
i) コンパイル時やプログラム実行時に,そのつどパッケージの起点となるディレクトリの場所を指定する
ii) 環境変数CLASSPATHに,パッケージの起点となるディレクトリの場所を追加する
ここでは,i)の方法を紹介する。(ii)の方法についてはこちらを参照せよ)
コンパイルは,次のように行う。
(1) コマンドプロンプトを表示して,MeiboTest01.java を保存したディレクトリにcdコマンドで移動。
例:もし,MeiboTest01.java を Z:¥ooprog に保存しているなら,
> cd Z:¥ooprog
とする。
(2) 次のように,パッケージの起点となるディレクトリの場所を指定してMeiboTest01.java をコンパイルする。
> javac -cp "Z:\MyDocuments\myclasses" MeiboTest01.java
※-cpは,javacコマンドのクラスパスを指定するためのオプションである。javacコマンドのオプションについては
> javac -help
とすれば概要が表示される。
コンパイルがうまくいかない場合は,
・ファイル配置が,手順2のFig.10のようになっているか(ディレクトリ名の間違いなどにも注意)
・Meibo.javaに,正しくpackage宣言が書かれているか
・MeiboTest01.javaに,正しくimport宣言が書かれているか
を確認せよ。
コンパイルがうまくいくと,Meibo.classとPerson.classが jinji ディレクトリの中に出来ているはずであるので,
確認せよ(下図)。
ここで起こったことを順序立てて書くと次のようになる。
1)javacコマンドがMeiboTest01.javaをコンパイルするとき,必要になるMeiboクラスが見つか
らないので,-cpオプションで指定されたファイルパスによりパッケージ階層の起点であるディ
レクトリ(この場合,Z:\MyDocuments\myclasses)を割り出す。
2)次いで,パッケージ階層の起点ディレクトリ(myclasses)とimport宣言の内容から
Z:\MyDocuments\myclasses\com\tuisjava\jinji
ディレクトリにクラスファイルMeibo.classがあるのではないかと推測する。
3)しかし,そのjinjiディレクトリ内には,コンパイル済みのMeibo.classはまだ無い。そこで
javaコンパイラは,Meiboクラスを定義しているはずのソースファイルMeibo.javaを探す。そ
うして,jinjiディレクトリ内にMeibo.javaを見つけたjavaコンパイラは,Meibo.javaを
コンパイルしてjinjiディレクトリの中に,Meibo.classとPerson.classを生成したのである
(上図の矢印)。Personクラスについても同様である。
手順6)手順の5でコンパイルしたMeiboTest01.classを実行してみよう。コマンドプロンプトの現在位置
(カレントディレクトリ)にMeiboTest01.classがあることを確認せよ。実行コマンドは以下のよう
になる。クラスパスに,MeiboTest01.classの在処であるカレントディレクトリ(.)を追加している
ことに注意。なお,カレントパスの区切り文字はWindowsではセミコロン(;),Unixではコロン(:)が
使われる。
> java -cp "Z:\MyDocuments\myclasses;." MeiboTest01
※-cpは,javaコマンドのクラスパスを指定するためのオプションである。javaコマンドのオプションについては
> java -help
とすれば概要が表示される。
※Eclipseで,パッケージを扱う方法については,左欄の「4. Eclipseでパッケージを作成する方法」のリンク先を参照せよ。