クラスを理解する(後編)

【第9回】クラスを理解する(後編)

3.Javaで「クラス」を表現する

ここからは、Javaで実際に「クラス」を見ながら話を進めていきましょう。
まず、これからの説明の為に、プログラム全体を示します。
これまでの例ではコンピュータを出してきましたが、ここではもっと簡単な題材として、貯金箱を「クラス」で表現してみましょう。
ファイル名:PiggyBank.java

  /* 貯金箱クラス。 */
  class PiggyBank                               // (1)
  {
      /* 貯金箱に入っている金額。 */
      int totalMoney = 0;                       // (2)
      
      /* 貯金箱にお金を入れる。 */
      void putCoin(int money)                   // (3)
      {
          totalMoney = totalMoney + money;      // (4)
          System.out.println("貯金箱に" + money + "円を入れました。");
      }
      
      /* 貯金箱を壊して、お金を取り出す。 */
      int breakPiggyBank()                      // (5)
      {
          System.out.println("ガシャン!");
          
          return totalMoney;
      }
      
      public static void main(String[] args)
      {
          // 貯金箱インスタンスを作る
          PiggyBank bank = new PiggyBank();     // (6)
          
          // 貯金箱にお金を入れる
          bank.putCoin(100);                    // (7)
          bank.putCoin(50);
          
          // 貯金箱を壊してお金を取り出す
          int money = bank.breakPiggyBank();    // (8)
          System.out.println("貯金箱から" + money + "円を取り出しました。");
      }
  }

どうですか?
今までのプログラムより、少し複雑かもしれませんね。
では、実際に手で打ち込んで、プログラムを動かしてみてください。

うまく動かせたら、以下のような結果になるはずです。

> java PiggyBank
貯金箱に100円入れました。
貯金箱に50円入れました。
ガシャン!
貯金箱から150円を取り出しました。

では、いつものように、少しずつプログラムの中身を見ていきましょう。

まずは、「クラス」を作るよ、という宣言を書きます。

  /* 貯金箱クラス。 */
  class PiggyBank                               // (1)

ここでは、クラスの名前を書く必要があります。貯金箱クラスには、「PiggyBank」という名前をつけました。ブタさんの貯金箱のつもりです。

上の宣言から下に続いている、中カッコの間(一番外の ‘{‘ から ‘}’ まで)が、「貯金箱クラス」の定義になります。

さて、「クラス」に定義する性質には「フィールド」と「メソッド」があると説明しました。なので、「貯金箱クラス」の定義にこれらを実際に定義して、「貯金箱クラス」の定義が完成します。

■ここまでのまとめ■

・「クラス」は宣言を書く必要がある。
・「クラス」の宣言には、名前が必要である。
・「フィールド」と「メソッド」は、「クラス」の宣言から続く中カッコの間に書く。

4.クラスの構成要素その1:フィールド

まず最初に、「フィールド」を見てみましょう。
フィールドは、「クラスが持つ情報を定義する」のでしたよね。

さて、貯金箱にはどのような情報を持たせましょうか。そうですね、貯金をすれば、お金が貯まっていきます(あたりまえですね)。なので、お金を入れていった結果、貯金箱の中にあるお金の合計が情報になります。
そこで、「貯金箱の中にあるお金の合計」を定義してやります。

      /* 貯金箱に入っている金額。 */
      int totalMoney = 0;                       // (2)

合計は、「totalMoney」という名前にしました。
「フィールド」を定義する時は、どんな種類の情報かを指定してあげる必要があります。それが、「totalMoney」の左にある「int」というキーワードです。貯金箱はお金の合計という数値を扱うので、このようになります。

もちろん、用意したばかりの貯金箱には何も入っていないので、最初は0(円)からスタートです。

■ここまでのまとめ■

・「フィールド」は、「クラスが持つ情報を定義する」。
・「フィールド」の定義では、情報の種類を指定する必要がある。

5.クラスの構成要素その2:メソッド

次に、もう一つの要素である「メソッド」を見てみましょう。
メソッドは、「インスタンスを操作する方法を提供する」のでしたよね。

「フィールド」と同じように、ここでも貯金箱に対する操作を考えてみます。貯金箱はお金を貯めるものですから、まず最初に「お金を入れる」という操作が思いつくと思います。
そこで、下のようなメソッドを定義してみました。

      /* 貯金箱にお金を入れる。 */
      void putCoin(int money)                   // (3)

お金を入れるメソッドは、「putCoin」という名前にしました。
「putCoin」の左側には「void」、右側にはカッコの中に「int money」と書かれていますね。
これは、メソッドの「入力」と「出力」を指定するものです。具体的には、右側(int money)が「入力」、左側(void)が「出力」です。

「貯金箱にお金を入れる」操作には、貯金箱に入れるお金が必要です。
なので、「入力」として「int」(=数値)という種類で「money」という名前の情報を指定したのです。
反対に、この操作で貯金箱からは何も出てこないので、「出力」は無いと言えます。「void」というキーワードは、「何も無い」ということを指定するものです。

■ここまでのまとめ■

・「メソッド」は、「インスタンスを操作する方法を提供する」。
・「メソッド」の定義では、名前の右側カッコに「入力」、左側に「出力」を指定する。
・「void」というキーワードは「(出力が)何も無い」ことを指定する。

話を戻しましょう。
貯金箱にお金が貯まったら、使いたいと思うでしょう。使うためにはお金を取り出さなければなりませんね。この貯金箱はブタさんの貯金箱なので、お金を取り出すには壊さなければなりません。
そこで、下のようなメソッドを定義してみました。

      /* 貯金箱を壊して、お金を取り出す。 */
      int breakPiggyBank()                      // (5)

今度は、先ほどの「putCoin」とは反対ですね。「出力」の部分が「int」になっています。
貯金箱を壊した結果、それまでに貯まっていたお金が取り出せるので、これがこのメソッドの「出力」になります。

一方、貯金箱を壊すのに必要な「入力」はありません。この場合は、カッコの中に何も書きません。これで「入力」が無いことを指定します。

これで、「貯金箱クラス」を定義することができました。でも、このままではこのプログラムは動きません。なぜでしょうか?
それは、この「貯金箱クラス」を使ってあげてないからです。どんな貯金箱も使ってあげてナンボです。

つまり、「クラス」が「定義」であり、実際にはインスタンスに具体化して使ってあげなければならないのです。

■ここまでのまとめ■

・メソッドの「入力」が無い場合は、カッコの中に何も書かない。
・「クラス」の定義だけでは、プログラムは動かない。動かす為にはインスタンスを作る必要がある。

6.クラスを使う

それでは、最後に「クラス」を使う部分を見てみましょう。

今回のプログラムで「クラス」を使っているのは、今まで説明に出てこなかった(でも実は、今まで何度も登場している) main メソッドです。

      public static void main(String[] args)
      {
          // 貯金箱インスタンスを作る
          PiggyBank bank = new PiggyBank();     // (6)
          
          // 貯金箱にお金を入れる
          bank.putCoin(100);                    // (7)
          bank.putCoin(50);
          
          // 貯金箱を壊してお金を取り出す
          int money = bank.breakPiggyBank();    // (8)
          System.out.println("貯金箱から" + money + "円を取り出しました。");
      }

main メソッドも、このクラスの「メソッド」です。が、少し特殊なメソッドです。というのも、main
メソッドは、プログラムを実行した時に、最初に呼び出されるメソッドだからです。

なので、実際に「クラス」を使うプログラムは、ここから始めます。

■ここまでのまとめ■

・main メソッドは、プログラムを実行したときに最初に呼び出される。
・実際に「クラス」使うプログラムは、main メソッドから始める。

main メソッドを見ていくと、最初に以下のような文が出てきます。

 // 貯金箱インスタンスを作る
 PiggyBank bank = new PiggyBank();     // (6)

今までの回で見てきた文とは、どこか違いますね。これが、PiggyBank クラスの「インスタンス」を作る文です。
(6) のように書くと、 bank という変数に、PiggyBank クラスのインスタンスを代入します(代入については第5回を参照)。
ここで注目するのは、new というキーワードです。これを使うことで、新しいインスタンスを作ってやります。

bank という変数は、すなわち PiggyBank クラスのインスタンスですから、以後は「インスタンスbank」と呼ぶことにします。
これで、これまでで定義してきた「貯金箱クラス」を使う準備が整ったわけです。

では、早速メソッドを呼び出してみましょう。まずは貯金箱にお金を入れる、putCoin メソッドを呼び出してみます。インスタンスbankの putCoinメソッドを呼び出すには、以下のように書きます。

 // 貯金箱にお金を入れる
 bank.putCoin(100);                    // (7)
 bank.putCoin(50);

最初の呼び出しで、インスタンスbank に100という値を追加したことになります。そして、その次の呼び出しでインスタンスbank に 50という値を追加したことになります。

こうして言葉にすると、あたかもインスタンスbank には合わせて150という値が入っているように思われます。ところで、プログラムではどのように実現しているのでしょうか?
少し戻って、putCoin メソッドの中にその答えはあります。

 totalMoney = totalMoney + money;      // (4)

totalMoney は PiggyBank クラスのフィールドであり、 money は putCoinメソッドの「入力」です。つまり、(4) では totalMoney
に putCoin メソッドを呼び出したときの値を足していることになるのです。

totalMoney「フィールド」は貯金箱クラスの合計金額という情報です。ですから、インスタンスbank ではこの totalMoney に具体的な値を入れて使用します。

インスタンスbank に設定した値は、そのまま次に使うことができます。なので、最初のputCoin メソッド呼び出しでは(最初の値である)0に100を足すことになります。同様にして、次の呼び出しでは最初の呼び出しの結果である100に50を足し、最終的に150になるのです。

■ここまでのまとめ■

・「クラス」から「インスタンス」を作るには、new というキーワードを使う。
・「メソッド」を呼び出すには、インスタンスを代入した変数とメソッド名をピリオド(’.’)でつなぐ。
・メソッドの中に定義した処理で、フィールドの値を変更することができる
・インスタンスに設定した値は、そのまま次に使うことができる。

さて、プログラムの中身を見ながら、理屈では説明したように動きそうだと思えてきたでしょう。では、実際にはどうか見てみましょう。
もう一つのメソッドである breakPiggyBank メソッドを呼び出してみます。

 // 貯金箱を壊してお金を取り出す
 int money = bank.breakPiggyBank();    // (8)

ここで、プログラムは画面に以下の出力をします。

ガシャン!

実は、この時点では画面に「貯金箱から150円を取り出しました」 と表示していません。150(円)という値は、(8)
の呼び出しの結果、 money 変数に代入されただけなのです。
したがって、その次の println メソッド呼び出しによって、その値を画面に表示して、このプログラムは終了となります。

7.まとめ

これで、Javaでクラスを扱う知識を、あなたも手に入れることができました。
様々な言葉が出てきたので、ここでもう一度整理しておきましょう。

01. オブジェクト指向は、ソフトウェアをオブジェクトを中心に考える「視点」である。
02. オブジェクトは、ソフトウェアの中の「もの」と考えられる。
03. 「クラス」は、オブジェクトの情報を一般化した「定義」である。
04. 「クラス」を具体化したもの(=オブジェクト)を「インスタンス」と呼ぶ。
05. 「クラス」に定義する性質には「フィールド」と「メソッド」がある。
06. 「フィールド」は「クラス」自身の属性である。
07. 「メソッド」は「インスタンス」を操作する方法を提供する。
08. 「クラス」は宣言を書く必要がある。
09. 「クラス」の宣言には、名前が必要である。
10. 「フィールド」と「メソッド」は、「クラス」の宣言から続く中カッコの間に書く。
11. 「フィールド」は、「クラスが持つ情報」を定義する。
12. 「フィールド」の定義では、情報の種類を指定する必要がある。
13. メソッドの「入力」が無い場合は、カッコの中に何も書かない。
14. 「クラス」の定義だけでは、プログラムは動かない。動かす為にはインスタンスを作る必要がある。
15. 「クラス」から「インスタンス」を作るには、new というキーワードを使う。
16. 「メソッド」を呼び出すには、インスタンスを代入した変数とメソッド名をピリオド(’.’)でつなぐ。
17. メソッドの中に定義した処理で、フィールドの値を変更することができる。
18. インスタンスに設定した値は、そのまま次に使うことができる。

どうでしょうか。今は、「なんとなく」でもOKです。以後の回で、いろいろな使い方を見ていきますので、少しずつ覚えていきましょう。

→ 次へ(第10回:複数のクラスを扱う)