パッケージ、アクセス修飾子

名前空間、パッケージ

  • プログラミングでは、名前をつける作業が沢山ある。クラス名、フィールド名、メソッド名、インスタンス名(変数名)、等々。これらの名前を適切につけることはわかりやすいプログラムを書くことにおいて非常に重要。
  • 名前がかぶると困る。
  • 名前空間(Namespace)
  • Java言語における名前空間の仕組み: パッケージ
  • パッケージ名はユニーク(一意)なものをつける。ドメイン名を逆から記述するのが慣例。
  • 今回は「lesson05.ユーザ名」

NetBeansでパッケージを作る

ソースパッケージを右クリックして新規、Javaパッケージ選択。

Newpackage1

パッケージ名を入力。場所がソースパッケージになっていることを確認。

Newpackage2

ソース・パッケージの下にできていることを確認。

Newpackage3

パッケージに対応してフォルダ(ディレクトリ)ができていることを確認。

Newpackage4

パッケージに所属するクラスを定義する

Newclass

  • パッケージのフォルダ内にクラスファイル(.java)を作成する。
  • パッケージ宣言を記述する。

同じパッケージに所属するクラスから使う

Bookクラスと同じようにMainクラスを作って、そこからBookクラスを使ってみよう。

Mainクラスにもpackage宣言がついたくらいで、これまでと特に違いはない。

違うパッケージに所属するクラスから使う

デフォルトパッケージにLesson05クラスを作成し、その中のmainメソッドから先ほどのBookクラスを使ってみよう。

違うパッケージから使うには、単にクラス名ではなく「パッケージ名.クラス名」で記述する。クラス名だけで使えるのは、同じパッケージに所属する(あるいはデフォルトパッケージに所属している)クラス。

ただし、まだこの状態ではエラーが出る。パッケージが異なるクラスからのアクセスには制限がかかっているからである。

アクセス修飾子

クラスの利用に関して制限をかけることができる。実は何も指定していない場合でも制限がかかっている。この利用の制限を設定するのが「アクセス修飾子」である。

アクセス修飾子の意味は4種類ある。とりあえず重要なのはpublicとprivate。

  • public
  • private
  • なし(つけない)
  • protected

どのような意味があるかは教科書を参照しよう。今回関係があるのは、「パッケージが同じ場合」と「パッケージが違う場合」について。

アクセス修飾子をつける対象はクラスとメンバー(フィールドとメソッド)。

先ほどのLesson5.javaのコンパイルエラーをなくすには、

  • Bookクラスを使うからclass Bookにpublicをつける。
  • コンストラクタを使うからコンストラクタにpublicをつける。
  • printInfoメソッドを使うからprintInfoメソッドにpublicをつける。

というように修正すれば良い。(注: このように「利用する側の都合」で「呼び出される側」を修正する、というのは設計がうまくいっていないことなので、あまり良くない。本来は、利用されるケースを想定してアクセス修飾子を適切に設定する)

これで、Lesson05.javaはコンパイルできるようになった。

ついでに、フィールドにはアクセスできない(例えば、book.price = 1000;等はエラーになる)ことを確認しておこう。

import

別のパッケージに所属しているクラスを使うには「パッケージ名.クラス名」とすれば良い。ただ、長くて面倒。

importを使うと、「パッケージ名.」を省略することができる。

import lesson05.d00000.Book;としておけば、このファイル内で「Book」と出てきたら、それは「lesson05.d00000.Book」という意味になる。

よくある質問

Q: パッケージに階層構造(包含関係)は?

A: ない。格納する場所(ソースコードの置き場所)は階層構造になるけど、各パッケージはなんの関係もできない。例えば「lesson05.p」と「lesson05.p.q」に包含関係は(見た目はありそうだけど)ない。

メソッド

メソッドとは(復習)

  • メソッドとはC言語の関数のような、「処理がまとめられたもの」である。
  • メソッドはクラスの中に作られる。
  • メソッドを実行するときに値を渡すことができる。その値のことを引数という。
  • メソッド内では、引数以外にも、インスタンスにあるフィールドも使うことができる。もちろんメソッド内で作った変数も使える。
  • メソッドの処理結果(値)を呼び出し元に返すことができる。その値を戻り値(返り値)という。

メソッドの例

Bodyクラスを題材にメソッドの実装例を見ていこう。実装したBodyの利用例も参照すること。

引数がなくて返り値がある

returnで返り値を指定する。

引数が1つで返り値がない

返り値がない場合は返り値の型の代わりに「void」と書く。

引数が2つで返り値がない

引数が複数の場合は「,」で区切る。

引数の名前がフィールドとかぶる場合、単にその名前を書くと引数の方が使われる。このような状況でフィールドの方を使うには「this.フィールド名」とする(教科書P.98)。

コンストラクタ

コンストラクタは「インスタンス化のときに実行されるメソッド」である。

例えば、これまではインスタンスを作成した後にフィールドに値を代入していたが、インスタンス化と同時に値を代入できるようなコンストラクタを定義してみよう。

コンストラクタの定義の注意点(普通のメソッドとの違い)は以下の2点。

  • コンストラクタの名前はクラス名と同じにする。自由につけられるわけではない。言い換えると、クラス名と同じ名前のメソッドはコンストラクタである。
  • コンストラクタには返り値がないので、返り値の型は記述しない。voidも書いてはいけない。

このコンストラクタを使ってインスタンスを作るには次のようにする。

ただし、この状態(コンストラクタを1つ定義した状態)でコンパイルしようとすると、Bodyクラスを呼び出しているクラス(Lesson03やLesson04)がエラーになってしまう。これは、「new Body()」に対応したコンストラクタが用意されていないからである。

「new Body()」に対応したコンストラクタも定義しよう。ここでは、乱数で身長と体重をセットすることにする。

これで、「new Body()」も使えるようになった。

そもそも、これまではなぜコンストラクタを定義していないのに「new Body()」でインスタンス化できていたのだろうか?それは、コンストラクタを1つも定義しない場合は、デフォルトコンストラクタという何もしないコンストラクタが生成されていたからである(教科書P.76)。デフォルトコンストラクタは、「コンストラクタを1つも記述しない場合」にだけ生成されることに注意すること。