10 複数のクラスを扱う

【第10回】複数のクラスを扱う

前回の講座はどうでしたか? 一通り、「Javaでクラスを表現する」ということを見てきました。
最初のうちは、習うより慣れろということで色々なプログラムを見ていくのが良いのです。 というわけで、どんどん次に進んでいきましょう。
今回は、1つだけのクラスから、複数のクラスへと発展させます。 クラスの中身を細かく見ていくよりも、オブジェクト指向らしく、 複数のオブジェクト同士が関連するプログラムを見ながら、Javaのクラスを覚えていきましょう。

前提:前回の講座を読み、(全てはわからなくとも)自分なりに考えてみたこと。

今回は、ClassSampleクラスと、AnotherClassSample クラスの2つを作成します。 以下にソースコードを掲載しますので、打ち込んでみてください。2つのソースコードは別のファイルとして、
それぞれのクラス名と同じファイル名をつけて保存してくださいね。
ファイル名:ClassSample.java

public class ClassSample
{
    private String msg;                                  // (1)

    public ClassSample()
    {
        System.out.println("Constructor Was Called.");   // (2)
    }

    public void setMessage(String inMsg)
    {
        msg = inMsg;                                     // (3)
    }

    public void printMessage()
    {
        System.out.println("message:" + msg);            // (4)
    }

    public static void main(String[] args)
    {
        ClassSample classSample;                         // (5)

        classSample = new ClassSample();                 // (6)
        classSample.setMessage("Hello Java World!");     // (7)
        classSample.printMessage();                      // (8)

        AnotherClassSample anotherClass = new AnotherClassSample(); // (9)
        anotherClass.printName();                        // (10)
        anotherClass.setName("bar");                     // (11)
        anotherClass.printName();                        // (12)
    }
}

ファイル名:AnotherClassSample.java

public class AnotherClassSample
{
    private String name;                                         // (A)

    // コンストラクタ
    public AnotherClassSample()                                  // (B)
    {
        System.out.println("AnotherClassSample Constructor!!");  // (C)
        name = "foo";                                            // (D)
    }

    // 名称設定
    public void setName(String new_name)
    {
        name = new_name;                                         // (E)
    }

    // 名称表示
    public void printName()
    {
        System.out.println("My name is " + name + ".");          // (F)
    }
}

それでは早速 ClassSample クラスをコンパイルし、実行してみましょう。 コンパイルできましたか?
修正を施した ClassSample.java を正しくコンパイルするためには、
ClassSample.java と AnotherClassSample.java を同じディレクトリに
保存しておかなければなりません。

もし、ClassSample.java が保存されているディレクトリにAnotherClassSample.java が
存在しない場合は、コンパイルした際に、以下のようなメッセージが出力されるでしょう。

C:\work>javac ClassSample.java
ClassSample.java:28: エラー:  シンボルを見つけられません
        AnotherClassSample anotherClass = new AnotherClassSample(); // (9)
        ^
  シンボル: クラス AnotherClassSample
  場所:  ClassSample
ClassSample.java:28: エラー: シンボルを見つけられません
        AnotherClassSample anotherClass = new AnotherClassSample(); // (9)
                                              ^
  シンボル: クラス AnotherClassSample
  場所:  ClassSample
エラー 2 個

C:\work>

このようなエラーメッセージによりコンパイルができなかった人は、
保存ディレクトリを確認してみてください。
(それでもダメな場合には、第2回の講座でCLASSPATHの設定を疑ってみましょう)

正しくコンパイルができ、実行した場合は以下のような結果が出力されます。

C:\work>java ClassSample
Constructor Was Called.
message:Hello Java World!
AnotherClassSample Constructor!!
My name is foo.
My name is bar.

C:\work>

この実行結果から、

(9):AnotherClassSample のコンストラクタが呼び出される。
(10)と(12):AnotherClassSample フィールドである名称情報の表示を行う。
(11):名称をセットしている。
がわかるかと思います。 実行したものはClassSampleでしたが、その内部では
AnotherClassSampleクラスのインスタンスが生成され、メソッドが使用されていますね。
ここで「あれっ?」と思ったあなた。その鋭さに脱帽です。

AnotherClassSample anotherClass = new AnotherClassSample(); // (9)

ClassSampleクラスのインスタンスを生成する時には、(5)で宣言を行い(6)で生成しましたよね。
今回は(9)で宣言と生成を一度に行っています。
つまり(5)と(6)も”ClassSample classSample = new ClassSample();”と書けるのです。

(10)での printName() メソッドの実行時には、AnotherClassSampleクラスのフィールドである
nameの値が、(D)で指定した通り、”foo” でしたが、(11)によりnameの値は”bar”に変更
(実際には(E)で設定)されたために、(12)のprintName() メソッドの実行結果には、
“bar” が表示されます。

ここで少し考えてみてください。
1つのクラスだけではなく、他のクラスに機能を分類することに一体何のメリットがあるのでしょうか。

機能ごとにクラスを分割しておくことで、これまでのクラスを再利用し易くなります。
今回の例では単純なものしか扱っていませんが、名称のデータを保存し、
画面に表示してくれるクラス(AnotherClassSample)があれば、後で再び利用するのが容易ですし、
その処理に何か変更を加えたいと思ったときには、
AnotherClassSample クラスのみを修正すればよいのです。
逆になんでもかんでも1つのクラスに入っていては、変更、修正が大変になってしまいますね。

もちろん、これだけが分割を行う理由ではないのですが、
今のところはこういった背景があるのだということを覚えておいてください。

かといって、むやみやたらと色々なクラスに分割すればよいというわけではありません。
あんまりにも細かく分かれていたら、作った本人も、一体どういうクラス構成なのか
わからなくなってしまうでしょう。第一、そのクラス群を使う人は大変ですよね。

それでは、今回の講座の内容をまとめてみましょう。

~まとめ~
1.2つのクラスを使ってみることが出来た
2.クラスの宣言とインスタンスの生成は、1行で書ける事がわかった
3.クラスを分類する理由を知った

今回の講座では、複数のクラスについて学び、いよいよ「サンプルプログラム」域から
抜け出した観があります。
「今は未だ作り方がわからないけれど、あんなプログラムを作りたい!」といった欲が
でてきた頃ではないでしょうか? それでは、今回はここまでとしましょう。

→ 次へ(第11回:プログラムの3大要素の1つである処理を扱ってみる)