Java のクラスについて

本日のTIL

今回は「やさしいJava」を読んで Java のクラスについて学んだ中で今まで意識できていなかった考え方や馴染みのなかった書き方、概念などについて書きます。

クラスの機能

カプセル化

カプセル化についてはもちろん Java を学び始める前もなるべく意識してコードを書いてきたので詳しくは書きませんが、全てのメソッドの先頭に public private とついているとわかりやすいなと思いました。 ( Ruby で private 以下が長くなって「結局これ private メソッドなの?」みたいになること、うーん、あるのか……?)

メソッドのオーバーロード

Java では 同じクラスの中に、同じ名前を持つメソッドを複数定義すること ができ、これを メソッドのオーバーロード といいます。 ちなみに、コンストラクタもオーバーロードすることができます。

効果

  • 似たような複数の処理を、1つのメソッド名を覚えて使うだけで自動的に型や個数に応じた処理が行われる。
  • 似たような処理について同じメソッド名を利用することができる。
  • 1つの名前が別々の働きを持つことを多様性というが、これが生まれる。

注意点

  • オーバーロードするメソッドは引数の型もしくは個数が異なってなければならない。

余談

Ruby にはないものですね ( そうですよね? ) 。 これができるのはやはり静的型言語の強みなのかなと思います。 今まで JS や Ruby しか書いていなかったので、同じ名前のメソッドを同じクラス内に定義するというとびっくりしますが、考えてみればとても便利ですね。 Ruby だと、個数の違いに対応するために引数にデフォルト値を入れたり配列やハッシュを引数にしたり、引数の型で処理を分けるためにメソッドの中で調べたりすると思いますが、 Java だとその必要がなくて、一つのメソッドが無駄に長くならなくて嬉しいですね!

インスタンス変数・インスタンスメソッド

  • オブジェクトに関連づけられているフィールドをインスタンス変数
  • オブジェクトに関連づけられているメソッドをインスタンスメソッド

と言います。

インスタンス変数・インスタンスメソッドはオブジェクトが作成された時にアクセスできるものです。

クラス変数・クラスメソッド

クラスに関連づけられているフィールドを クラス変数 、メソッドを クラスメソッド と言います。 これらはインスタンス変数とは異なり、クラス全体に関連づけられます。 クラス全体で扱うデータを格納しておくフィールド がクラス変数、 クラス変数を出力するなど、 クラス全体に関わる処理を行う のがクラスメソッドです。 クラスメソッドはオブジェクトが作成されていなくても呼び出せます。 代表的なクラスメソッドとして main() メソッドがあります。

注意点

  • this. はインスタンスメソッドの中でしかつけられない。

ローカル変数

メソッドの中で宣言する変数やメソッド内で使われる仮引数のことを ローカル変数 と言います。

注意点

  • 慣習として、インスタンス変数・クラス変数では内容がわかりやすい長い変数名を使うことが多いのに対し、ローカル変数は内容をコンパクトに表した短い変数名を使うことがある。
  • 宣言したメソッド以外の場所では使えない。
  • メソッドが呼び出されるたびに初期化される。

クラス型の変数への代入

例えば Car というクラスがあった場合

Car car1 = new Car();

Car car2;
car2 = car1;

このように、 クラス型の変数に同じクラス型の変数を代入する ことができるようになっています。

ここで注意したいのは 代入された変数がもう一方の変数の指しているオブジェクトを指すようになる ということです。 つまり、複数の変数が一つのオブジェクトを指している状態になるということですね。

nullの仕組み

クラス型の変数に null を代入するとその変数は どのオブジェクトもあらわさなく なります。 さらに、そのオブジェクトがどの変数からも扱われなくなった場合はGCの働きでオブジェクトが破棄されます。 ただし、複数の変数が同じオブジェクトを指していた時は、一つに null が代入されただけではオブジェクトが破棄されることはありません。

finalize() メソッド

オブジェクトが作成されるときにコンストラクタが自動的に呼び出されたのと同じように、オブジェクトが破棄される時は finalize() メソッドが自動的に呼び出されます。 ただし、Java の GC によってオブジェクトは破棄されるため、 finalize() が呼び出されるタイミングを管理することはできません。

スーパークラスのコンストラクタ

Java スーパークラスを拡張してサブクラスを定義することができます。 サブクラスのオブジェクトが作成された時、特に何も指定していない場合は サブクラスのコンストラクタ内の先頭で、スーパークラスの引数のないコンストラクタが呼び出され ます。 ただし、 super() を記述すると どのコンストラクタを呼び出すか指定できる ようになります。

super(arg1); // 引数1つのコンストラクタが呼び出される
super(arg1, arg2, arg3); //引数3つのコンストラクタが呼び出される

注意点

this() を使うとそのクラスの別のコンストラクタを呼び出すことができますが、 this()super() もコンストラクタ内の先頭に記述しなければならないので同時に使用する子はできません。

サブクラスからのアクセス

スーパークラスの private メンバにはサブクラスからもアクセスすることはできません。 スーパークラスでは protected という指定ができるようになっており、 protectedメンバにはサブクラスからアクセスすることができます。

オーバーライド

Java では スーパークラスと全く同じメソッド名・引数の数・型を持つメソッドを定義することができます。 様々なクラスのオブジェクトを管理する時、スーパークラスの配列変数で扱うことがありますが、オーバーライドをすることによって、 オブジェクトをまとめて扱うことができる ようになります。

super()

サブクラスからスーパークラスの同じ名前のメンバにアクセスする場合は super. をつけます。

finalの使い方

  • メソッドの先頭に final をつけるとオーバーライドされなくなる。
  • フィールドに final をつけると値を変更できなくなる。
  • クラスに final をつけるとクラスを拡張できなくなる。

toString()

  • Object クラスの toString() メソッドをオーバーライドすると、オブジェクトを表す文字列を定めることができます。

equals()

  • Object クラスの equals() メソッドでオブジェクトが同じかどうか調べることができる

getClass()

  • Objectクラスの getClass() メソッドで、オブジェクトのクラス情報を知ることができる

ふう。そろそろ所感

なかなか長くなりましたね。 オーバーロードとオーバーライドはなんだか言い間違えてしまいそうですねw どちらもオブジェクト指向プログラミングをする上では大切な考え方だと理解しています。 あとはとにかく実際にコードを読み書きして自然とそういう書き方ができるようになりたいですね。 次は抽象クラスやインターフェイスについてまとめます!

 
comments powered by Disqus