Javaオブジェクト解説「パッケージとアクセス修飾子」

プログラミング考え方講座

前回、Javaのオブジェクトに関連する3つの考え方を説明した。

以下の3つだ。

  • カプセル化
  • 継承
  • 多態性(ポリモーフィズム)

今回は、このうちカプセル化に焦点を当てていく

具体的には、タイトルに書いた通り、パッケージアクセス修飾子というものについて詳しく見ていく。

パッケージとは、各Javaソースコードの関係性を示すもの、アクセス修飾子どこから情報を見れるようにするのかという考え方だ。

これらが理解できて、初めてカプセル化の詳細な説明ができるようになる。

その前準備と思ってほしい。

スポンサーリンク

今回の説明内容

冒頭に書いてしまったが、改めて書いておこう。

今回は、Javaにおけるパッケージアクセス修飾子について解説する。

先に言っておくと、パッケージeclipseなどの統合開発環境を使用している場合には勝手にソースへ付与してくれていることが多い。

今回はそうではなく、メモ帳などで組んでいることを想定して書いてみよう。

パッケージ

パソコンのディレクトリを想像して欲しい。

あるディレクトリがあって、その中にはちょっと細分化されてまたディレクトリがある。

その細分化を繰り返し、最終的には実体のファイルが置かれている。

大体はこんな感じだと思う。

パッケージは、このディレクトリをソースコードで作るイメージだ。

例えば、ある処理を行う場合に、以下のようなディレクトリ構成を考えてみよう。

  • メインディレクトリ:実行するためのソースコードと、他のディレクトリを含む
    • モデルディレクトリ:モノを表現したクラスを定義する
    • 処理ディレクトリ:実際の処理を定義する
    • 出力ディレクトリ:情報を受け取り、画面に表示する処理を定義する

こんな感じだ。

このように考えたとき、この各ディレクトリを一つのパッケージというものの中に入れておくことができる。

複数ファイルに処理を記述する

まずはこれを解説しておこう。

これまでは、全てを一つのファイルの中に書いていた

しかし、実際には別のファイルに書くことも可能だ。

個人的な感覚になるが、一つのクラスを一つのファイルに書くことが多い

というわけで、前々回、オブジェクトの説明で書いていた本のサンプルコードを、まずは単純にクラスごとにファイル分けしてみよう。

以下二つのソースコードを同じディレクトリに入れておく。

public class Book {
    String title;
    String author;
    String date;
    int version;
    int price;

    public Book(String title, String author, String date, int version, int price){
        this.title = title;
        this.author = author;
        this.date = date;
        this.version = version;
        this.price = price;
    }

    public void versionUp(){
        this.version++;
    }

    public void showBook(){
        System.out.println(this.title + " : " + this.author + " : " + this.date + " : 第" + this.version + "版 : " + this.price + "円");
    }
}
public class Sample17 {
    public static void main(String args[]){
        Book book1 = new Book("本1", "著者1", "2020/03/23", 1, 1500);
        Book book2 = book1;

        System.out.println("book1の情報");
        book1.showBook();
        System.out.println("book2の情報");
        book2.showBook();

        book2.versionUp();
        System.out.println("book1の情報");
        book1.showBook();
        System.out.println("book2の情報");
        book2.showBook();
    }
}

Bookクラスのコンストラクタメソッドpublicというものをつけて、両クラスの前にもpublicをつけた。

これはどこからでも見えるようにするもので、後半で解説するアクセス修飾子というやつだ。

で、このように二つのファイルに分けても、何の問題もない

これのコンパイルはSample17.javaだけやればよく、実行もそのままできる。

ファイルをディレクトリに分ける

上で、クラスごとに別ファイルへ分けた

このクラスの数が増えてくると、そのクラスの特徴ごとに、今度はディレクトリへ分けたいとなるだろう。

今回は…まあ数が2つだけだが、それでもBookクラスは本をモデル化したものなので、modelというディレクトリに入れてしまおう。

二つのディレクトリがあり、以下のようになっている。

mainディレクトリ
∟Sample17.java
modelディレクトリ
 ∟Book.java

このようにディレクトリを移してそのままコンパイルしようとすると、Bookがないよというエラーが出てしまう。

このように、通常は同じディレクトリ内しか見ることができない

そこで、パッケージの出番となる。

まずは、Bookクラスを、mainの中のmodelというパッケージに入れたよということをファイルに書いてあげる。

先頭(クラス定義よりも前)に、以下1行を追加しよう。

package main.model;

これで、Bookクラスがmodelというパッケージに入った

後は、メインの処理が書かれているSample17.javaに、これ自体がmainというパッケージにあることと、Bookをを読み込むよう指示してあげればいい。

今度は、Sample17.javaの先頭に、以下2行を追加する。

package main;
import main.model.Book;

こうすることで、Bookを読み込む準備ができた。

後はコンパイルと実行だ。

ここでポイント。まずは、mainディレクトリがある場所に移動しよう。

Sample17.javaがあるところではなく、その一つ上だ。

そこで、以下のような形でコンパイルする。

javac -encoding UTF-8 main\Sample17.java

これでエラーが出なければOKだ。

あとは実行なのだが、これもちょっと普段とは異なる。

同じ場所で、今度は以下の形で実行する。

java main.Sample17

パッケージに入れた場合は、その一番大元となる場所(今回はmainディレクトリの一つ上)から、main関数があるファイルを指定してコンパイルする。

そうすると、そこから使用されているクラスも含めて同時にコンパイルされる。

あとは、パッケージの考え方で実行するクラスを指定すれば、実行されるというわけだ。

このパッケージは実際のディレクトリと対応しているので、照らし合わせて考えていこう。

アクセス修飾子

お次はこちら。

上でクラス名にpublicとつけていたり、以前もクラスの変数、メソッドにもつけたりつけなかったりしていた。

アクセス修飾子は、このpublicというやつだ。

こいつは何者なんだというのを解説していこう。

アクセス修飾子とは

アクセス修飾子とは、その情報をどこから参照可能にするかを決定するための記述だ。

例えば、クラスに定義するメソッドについて。

これを、そのクラス内でしか呼び出させたくない場合は、privateというものをつける。

逆に、どこからでも呼び出し可能にしたい場合は、publicというものをつける。

と、どこからアクセス可能かを判別するための修飾子だ。

これは4種類ある。

それぞれ、どこからアクセス可能かを表にまとめてみた。

アクセス修飾子同クラス内同パッケージ内継承先(サブクラス)その他
public
protected×
省略(記載なし)××
private×××

まだ具体例を説明してない継承が出てきてしまっているが、前回の例をちょっと思い出してみよう。

ゲームソフトを継承して、Nintendo 64ゲームキューブを作っていた。

このとき、ゲームソフトから見たNintendo 64やゲームキューブのソフトサブクラスという。

なので、ゲームソフト内にアクセス修飾子なしで定義した変数には、64やGCからはアクセスできない

それに対し、protectedをつけたら、アクセスできるようになる。

また、上の例でクラスpublicをつけていたが、クラスに設定できるのはpublicと省略の2種類のみ

そして、省略した場合は、当然のごとく別パッケージからは参照不可となる。

一つ注意だが、public修飾子をつけたクラスは、一つのファイルに対して一つしか定義できない

また、publicをつけたクラス名と、それを書いているファイルの拡張子前部分一致している必要がある

これに注意しておこう。

このアクセス修飾子のポイントは、できる限り狭い範囲で公開すること

全てpublicなどもってのほかなので、それぞれに対してどこまでアクセスするべきかをしっかり確認しよう。

具体例は…次回のカプセル化のところでまとめて出してしまおう。

まとめ

今回はパッケージアクセス修飾子について説明した。

パッケージは、ソースコードをディレクトリのような形で定義するもの

アクセス修飾子は、その内容をどこから見れるようにするかを指定するもの

これらのおかげで、ようやくカプセル化を説明することができる。

次回は、そのカプセル化の説明をしよう。

大きな具体例を一つ出して、それを細かく見ていくこととする。

更新情報はTwitterでも呟いている。よかったら、ページ下部のTwitterアイコンから覗いていってほしい。

それでは。

コメント

タイトルとURLをコピーしました