クラスは設計図
これまでのコードは、ただの値をやり取りするメソッドの中に存在していました。クラスを使うと、関連するデータと、それを操作する振る舞いを、1つの名前付きの型にまとめられます。クラスは設計図であり、実際に扱う対象はそこから生成されるオブジェクトです。
クラスは2種類のメンバーを宣言します。フィールド(各オブジェクトが保持するデータ)と、メソッド(各オブジェクトができること)です。
new Dog() はメモリ上にオブジェクトを構築し、その参照を返します。d.name と d.bark() はその特定のオブジェクトにアクセスします。
各オブジェクトは独自の状態を持つ
クラスの本質は、それぞれが独自のフィールド値を持つ多数の独立したオブジェクトを量産できる点にあります。1つを変えても、他には決して影響しません。
rex と bella は2つの別個のオブジェクトです。それぞれが独自の name を持つため、各 bark() は異なる値を表示します。このオブジェクトごとのデータをインスタンスの状態と呼びます。
フィールドとメソッドは連携する
クラス内のメソッドは、そのオブジェクト自身のフィールドを直接読み書きでき、パラメータとして渡す必要はありません。メソッドは、自分が触れるデータを持つオブジェクトの「上に存在している」のです。
increment() が引数を1つも取らないことに注目してください。呼び出した相手の Counter に属するフィールドに対して動作します。これがクラスメソッドと、独立した静的メソッドとの違いです。メソッドには、作用する対象となる暗黙のオブジェクトがあるのです。
thisキーワード
メソッドの中で this は、そのメソッドが呼び出されたオブジェクトへの参照です。通常は必要ありません。count と書けばすでに this.count を意味します。しかし、パラメータ名がフィールド名と衝突するときに this は不可欠になり、これはセッターやコンストラクタで絶えず起こります。
初心者がよくやる間違いは、move の中で x = x; と書くことです。これはパラメータを自分自身に代入するだけで、フィールドは手つかずのまま残ります。コンパイラは警告してくれず、オブジェクトは黙って古い値を保ち続けます。フィールドを実際に更新するのは this.x = x; です。
フィールドのデフォルト値とnull参照
オブジェクトを生成すると、そのフィールドはゴミ値のまま放置されません。Javaはデフォルト値で初期化します。数値は 0、boolean は false、String のようなオブジェクト参照は null です。この null のデフォルトが、古典的なクラッシュの原因になります。
u.name は誰も設定していないため null であり、その上で .length() を呼ぶと NullPointerException が投げられます。フィールドを使う前に、必ずオブジェクトへ意味のある値を代入しましょう。これこそコンストラクタが解決する問題です。
クラスを中心にコードを構成する
実際のプログラムは、データとそれに対する操作を一緒に保持するクラスとしてドメインをモデル化します。ここでは1つの BankAccount クラスが残高を保持し、その変化の仕方を管理します。
データ(balance)と、それを変更する規則(deposit、withdraw)が1か所にまとまっています。他の場所のコードは、口座の数値を直接いじるのではなく、口座に処理を依頼します。これが、きれいで保守しやすい設計の基礎です。
次へ:コンストラクタ
new のあとで各フィールドを手作業で設定するのは面倒で、忘れやすいものです。そして今見たとおり、設定し忘れたフィールドはクラッシュを待つ null を残します。コンストラクタを使えば、オブジェクトの生成と同時にそのフィールドを必須にして初期化でき、BankAccount が所有者なしで存在することは決してなくなります。それが次のページの内容です。
よくある質問
Javaのクラスとは何ですか?
クラスとは、ある種類のオブジェクトが持つデータ(フィールド)と振る舞い(メソッド)を定義する設計図です。クラスそのものはテンプレートにすぎず、実際のオブジェクトは new でそこから生成します。たとえば Dog クラスは、どの犬も name を持ち bark() できることを記述し、new Dog() のそれぞれが独自の名前を持つ別個の犬になります。
Javaにおけるクラスとオブジェクトの違いは何ですか?
クラスは定義であり、オブジェクトはその定義から new で作られる具体的なインスタンスです。1つの Person クラスから多数の Person オブジェクトを生み出せ、それぞれが独自のフィールド値を保持します。クラスはクッキーの抜き型、オブジェクトは個々のクッキーだと考えてください。あるオブジェクトのフィールドを変えても、別のオブジェクトには決して影響しません。
Javaのクラスでthisキーワードは何をしますか?
this は現在のオブジェクト、つまりそのメソッドを実行している特定のインスタンスを指します。オブジェクト自身のフィールドにアクセスするために使い、特にパラメータがフィールドと同じ名前の場合(this.name = name;)に役立ちます。this がなければ、その代入はパラメータを自分自身に代入するだけで、フィールドは変わらないままになります。