パパの勉強部屋

勉強の記録をつけています。Java、ネットワーク、Excel、etc.

スッキリわかるJava入門 第8章 インスタンスとクラス①

第8章 インスタンスとクラス①

オブジェクトを生み出す手順

  • プログラマの仕事
  • ①各オブジェクトが負うべき責務を考え、「属性」「操作」の種類と内容を定義する。
  • ②各オブジェクトを仮想世界に生み出し、動かす。
  • Javaでは、仮想世界の中で動くオブジェクトそのものをプログラマが直接定義することは許されない。
  • その代わりに、プログラマは「オブジェクトが生み出される際に用いられる、オブジェクトの設計図」であるクラスを定義できる。
  • ①クラスを定義する。
  • ②そのクラスに基づいてオブジェクトを生成する。

クラスとオブジェクトが別である理由

  • 「オブジェクトを大量に作る必要がある状況」を創造する。
  • たとえば、銀行で「口座」オブジェクトが1,000個必要な場合、それぞれに対して「属性として、残高・名義人・開設日があって…」という定義を繰り返すと、プログラマの作業は膨大になる。
  • クラスに「属性として、残高・名義人・開設日があって…」という定義をした「口座クラス」を1度作っておけば、このクラスから100個でも1,000個でも必要なだけオブジェクトを生み出す事ができる。
  • クラスは、プラモデル工場にある「金型」と同じと考えれば良い。元となる金型を1個作っておいて、そこにプラスチックを流し込んで、同じプラモデルを大量に製造する。
  • 改めて意識するのは、クラスとオブジェクトはまったく違うものであるという点。
  • プログラムの動作時に仮想世界の中で活躍するのは「オブジェクトだけ」であって、その金型であるクラスが仮想世界で活動することは基本的にはない。

オブジェクトという用語のあいまいさ

  • 「金型ではなく、その型から生み出され仮想世界で活動する実体」を厳密に示したい場合は、インスタンス(instance)という用語を用いる。
  • クラスからインスタンスを生成する行為をインスタンス化(instranciation)と表現する。

プログラムに登場する2種類のクラス

  • クラスから生み出された勇者やお化けキノコのインスタンスは、誰かから指示(操作の呼び出し)をもらえば責任を果たすために動いてくれるだけなので、この2人だけを開発しインスタンス化しても「指示待ち状態」になってしまう。
  • 2人の登場人物にどのように動くか指示を出していく必要がある。神様の指示である「天の声」はmainメソッドとして記述する。

登場人物クラスの作り方

勇者
名前
HP
戦う
逃げる
座る
転ぶ
眠る
  • あるクラスの設計内容を上から「クラス名」「属性」「操作」の一覧として並べる書き方は、クラス図(class diagram)という設計図の書き方ルールに準じたもの。
  • クラス図は世界共通の設計図の書き方であるUML(Unified Modeling Language)で定められている図の1つ。

public class Hero {
  String name;
  int hp;
  public void attack() {/* … */}
  public void sleep() {/* … */}
  public void sit(int sec) {/* … */}
  public void slip() {/* … */}
  public void run() {/* … */}
}

属性の宣言方法

  • 属性(名前、HP)についてプログラムで使用する変数の名前と型を考える。
  • 属性を宣言するにはクラスブロックの中に変数宣言を記述する。
  • クラスブロック内に宣言された変数を、Javaでは特にフィールド(field)と言う。

public class Hero {
  String name;  // 名前の宣言
  int hp;       // HPの宣言
}

属性の初期値指定と定数フィールド

  • フィールド宣言時に代入も同時に行うよう記述しておくと、そのフィールドの初期値を設定することができる。

public class Matango {
  int hp;
  int level = 10;
}

  • フィールド宣言の先頭にfinalをつけると、値を書き換えることのできない定数フィールドになる。
  • 定数フィールドは一目でそれと分かるように大文字で記述することが推奨される。

public class Matango {
  int hp;
  
  final int LEVEL = 10;
}

操作の宣言方法

  • 「操作」をプログラミングするには、まず「操作の名前」「操作するときに必要な情報の一覧」「操作の結果として指示元に返す情報」「処理内容」の4つを考える必要がある。

【名前】  sleep
【必要情報】なし
【結果】  なし
【処理内容】眠った後はHPが100に回復する

public class Hero {
  String name;
  int hp;

  void sleep() {
    this.hp = 100;
    System.out.println(this.name + "は、眠って回復した!");
  }
}

  • thisとは特別に準備された変数で、「自分自身のインスタンス」を意味している。
  • 同じクラス内のフィールドへのアクセスの場合、「this.」を省略しても動作する。
  • しかし、ローカル変数や引数にも同じhpという名前の変数があった場合、そちらが優先されてしまうなど予想外の動作になる可能性がある。
  • フィールドを用いるときは明示的にthisを付けるようにする。

クラス名とメンバ名のルール

  • クラス名、フィールド名、メソッド名はそれぞれ、基本的に識別子のルールを満たしていれば自由に決めることができる。しかし、実際には次のような慣例に従い、名前を付けることが望ましいとされる。
クラス名 名詞 単語の頭が大文字 Hero、MonsterInfo
フィールド名 名詞 最初以外の単語の頭が大文字 level、itemList
メソッド名 動詞 最初以外の単語の頭が大文字 attack、findWeakPoint

クラス定義のまとめ

勇者
名前
HP
眠る
座る
転ぶ
逃げる
  • 「属性」「操作」の一覧をクラス図にまとめ、それをJavaコードに置き換え「フィールド」と「メソッド」として記述していく。

public class Hero {
  String name;
  int hp;
  public void sleep() {
    this.hp = 100;
    System.out.println(this.name + "は、眠って回復した!");
  }
  public void sit(int sec) {
    this.hp += sec;
    System.out.println(this.name + "は、" + sec + "秒座った!");
    System.out.println("HPが" + sec + "ポイント回復した");
  }
  public void slip() {
    this.hp -= 5;
    System.out.println(this.name + "は、転んだ!");
    System.out.println("5のダメージ!");
  }
  public void run() {
    System.out.println(this.name + "は、逃げ出した!");
    System.out.println("GAMEOVER");
    System.out.println("最終HPは" + this.hp + "でした");
  }
}