名前空間、パッケージ
- プログラミングでは、名前をつける作業が沢山ある。クラス名、フィールド名、メソッド名、インスタンス名(変数名)、等々。これらの名前を適切につけることはわかりやすいプログラムを書くことにおいて非常に重要。
- 名前がかぶると困る。
- 名前空間(Namespace)
- Java言語における名前空間の仕組み: パッケージ
- パッケージ名はユニーク(一意)なものをつける。ドメイン名を逆から記述するのが慣例。
- 今回は「lesson05.ユーザ名」
NetBeansでパッケージを作る
ソースパッケージを右クリックして新規、Javaパッケージ選択。
パッケージ名を入力。場所がソースパッケージになっていることを確認。
ソース・パッケージの下にできていることを確認。
パッケージに対応してフォルダ(ディレクトリ)ができていることを確認。
パッケージに所属するクラスを定義する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package lesson05.d00000; class Book { String title; String author; int price; /** * コンストラクタ */ Book(String title, String author, int price) { this.title = title; this.author = author; this.price = price; } /** * 情報を表示するメソッド */ void printInfo() { System.out.println("タイトル: "+title); System.out.println("著者: "+author); System.out.println("税抜き価格: "+price); } } |
- パッケージのフォルダ内にクラスファイル(.java)を作成する。
- パッケージ宣言を記述する。
同じパッケージに所属するクラスから使う
Bookクラスと同じようにMainクラスを作って、そこからBookクラスを使ってみよう。
1 2 3 4 5 6 7 8 |
package lesson05.d00000; class Main { public static void main(String[] args) { Book book = new Book("Javaの絵本", "アンク", 1580); book.printInfo(); } } |
Mainクラスにもpackage宣言がついたくらいで、これまでと特に違いはない。
違うパッケージに所属するクラスから使う
デフォルトパッケージにLesson05クラスを作成し、その中のmainメソッドから先ほどのBookクラスを使ってみよう。
1 2 3 4 5 6 |
class Lesson05 { public static void main(String[] args) { lesson05.d00000.Book book = new lesson05.d00000.Book("Javaの絵本", "アンク", 1580); book.printInfo(); } } |
違うパッケージから使うには、単にクラス名ではなく「パッケージ名.クラス名」で記述する。クラス名だけで使えるのは、同じパッケージに所属する(あるいはデフォルトパッケージに所属している)クラス。
ただし、まだこの状態ではエラーが出る。パッケージが異なるクラスからのアクセスには制限がかかっているからである。
アクセス修飾子
クラスの利用に関して制限をかけることができる。実は何も指定していない場合でも制限がかかっている。この利用の制限を設定するのが「アクセス修飾子」である。
アクセス修飾子の意味は4種類ある。とりあえず重要なのはpublicとprivate。
- public
- private
- なし(つけない)
- protected
どのような意味があるかは教科書を参照しよう。今回関係があるのは、「パッケージが同じ場合」と「パッケージが違う場合」について。
アクセス修飾子をつける対象はクラスとメンバー(フィールドとメソッド)。
先ほどのLesson5.javaのコンパイルエラーをなくすには、
- Bookクラスを使うからclass Bookにpublicをつける。
- コンストラクタを使うからコンストラクタにpublicをつける。
- printInfoメソッドを使うからprintInfoメソッドにpublicをつける。
というように修正すれば良い。(注: このように「利用する側の都合」で「呼び出される側」を修正する、というのは設計がうまくいっていないことなので、あまり良くない。本来は、利用されるケースを想定してアクセス修飾子を適切に設定する)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package lesson05.d00000; public class Book { String title; String author; int price; /** * コンストラクタ */ public Book(String title, String author, int price) { this.title = title; this.author = author; this.price = price; } /** * 情報を表示するメソッド */ public void printInfo() { System.out.println("タイトル: "+title); System.out.println("著者: "+author); System.out.println("税抜き価格: "+price); } } |
これで、Lesson05.javaはコンパイルできるようになった。
ついでに、フィールドにはアクセスできない(例えば、book.price = 1000;
等はエラーになる)ことを確認しておこう。
import
別のパッケージに所属しているクラスを使うには「パッケージ名.クラス名」とすれば良い。ただ、長くて面倒。
importを使うと、「パッケージ名.」を省略することができる。
1 2 3 4 5 6 7 8 |
import lesson05.d00000.Book; class Lesson05 { public static void main(String[] args) { Book book = new Book("Javaの絵本", "アンク", 1580); book.printInfo(); } } |
import lesson05.d00000.Book;
としておけば、このファイル内で「Book」と出てきたら、それは「lesson05.d00000.Book」という意味になる。
よくある質問
Q: パッケージに階層構造(包含関係)は?
A: ない。格納する場所(ソースコードの置き場所)は階層構造になるけど、各パッケージはなんの関係もできない。例えば「lesson05.p」と「lesson05.p.q」に包含関係は(見た目はありそうだけど)ない。