JAVAの継承クラスは超簡単?オーバーライドやコンストラクタの仕組みは?インスタンス化してメソッドやメンバ変数へのアクセス方法!
Javaの魅力はなんといってもオブジェクト指向そのものです。
私もこのオブジェクト指向というものをようやく人に説明できるくらい理解ができてきたなと最近実感しました。
学生時代の頃からプログラミングに触れてきて今に至りますが、
特にJavaは高機能だけど、癖の強い言語で、「オブジェクト指向」の概念を捉えないと、
なかなか理解が深まらないものなんです。
しかし「オブジェクト指向」を理解するにはなかなか厳しいと思います。
この概念を簡単に説明すると、プログラムのコーディング手法を日常に見立てます。
登場する変数やクラス、メソッドをオブジェクトというデータの集まりを
それぞれ人や物に例えた表現や考えで構成するものですね。
ですが、この解説では100%正しい説明に至りません。
なぜなら、このオブジェクト指向というものはひとことでバスッと片づけられるものではないからです。
オブジェクト指向のひとつである「継承クラス」についてみていきたいと思います。
継承クラスのインスタンス
Javaのオブジェクト指向の概念のひとつ。
クラスを拡張する機能で「継承クラス」というものがあります。
子クラスにextends修飾子を付加することで、親クラスを指定することができます。
こうしたクラス同士には継承関係がありますね。
継承を用いると、各々のメンバ変数やメソッドを共通利用できたり、オーバーライドが使えます。
しかし、クラスの呼び出し元でインスタンス化して利用することができますが、
インスタンス化の指定方法によって動きが変わって来るんですよね。
例えば、以下のようなクラスが2つあった場合のインスタンスの違いを見ていきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Oya { public void a() { } //① public void b() { } //② } /* 子クラス */ public class Ko extends Oya { public void b() { } //③ public void c() { } //④ } |
親クラスだけのインスタンスを指定した場合
Oyaクラスだけのインスタンスを指定する場合は以下の通りですね。
1 | Oya o = new Oya(); |
このようなインスタンスを生成した場合、アクセスできるメソッドは、
もちろんOyaクラスだけになりますので、①②のみになります。
親クラスのインスタンスでは、子クラスの情報を呼び出せません。
子クラスだけのインスタンスを指定した場合
Koクラスだけのインスタンスを指定した場合は以下の通りですね。
1 | Ko k = new Ko(); |
Javaでは子クラスを呼び出した場合、親クラスのメンバ変数、メソッドも呼び出すことができますよね。
但し、親クラスと子クラスに引数、戻り値が一致した同名のメソッドが存在する場合、
子クラスのメソッドが優先されます。これをメソッドのオーバーライド(上書き)と言いますね。
この現象が発生した場合、子クラスのメソッドが優先され、親クラスのメソッドは無視されます。
上の例の場合では、アクセスできるメソッドは①③④のみになります。
尚、②は③によってオーバーライドされますので、アクセスできません。
継承クラスを実装した場合、メソッドを拡張したい場合には、このインスタンスを行ないますね。
親クラスと子クラスが混在したインスタンスを指定した場合
Javaでは特殊なインスタンスを生成することができます。
1 | Oya o = new Ko(); |
継承関係を持つ同士のクラスの場合、上記のような指定ができてしまいます。
Oyaクラス型の変数にKoクラスのインスタンスを代入するというケースですね。
このインスタンス指定をすると動作が若干変わってきます。
まずアクセスできるメソッドですが、親クラスに存在するメソッドのみになります。
しかし、ここでオーバーライドが発動します。
なので、子クラスに同じメソッドが存在する場合、子クラスのメソッドを優先するというものです。
つまり、親クラスのメソッドのみアクセスできるが、共通するメソッドのみ子クラスのメソッドを優先するという動きになります。
では子クラスを型とした変数に親クラスのインスタンスを生成できるか?
1 | Ko k = new Oya(); |
このまま記述すると「型の不一致」でエラーになってしまいます。
あくまで継承では親クラスを子クラスで拡張する為、軸となるクラスは親です。
なので親クラスの型で子クラスのインスタンスは生成できますが、その逆は原則できません。
というのはダウンキャストという変換を行なえばできますが、たいてい使うものではないので、
やめておきます。
継承クラスでのインスタンス化のまとめ!
では実際にこれらのインスタンスをどう使い分ければいいのでしょうか?
1 | (A) Oya o = new Oya(); |
上記のAの場合は、継承クラス実装前、もしくは親クラスだけで完結する処理に使うインスタンスです。
1 | (B) Ko k = new Ko(); |
では次に子クラスをインスタンス化した場合は、親クラスのメソッドも利用できますね。
しかし、オーバーライドが発生する場合は、その該当メソッドは子クラス側に優先されます。
つまり、親クラスに対して、
「メソッドを新しく追加したい」、「親クラスのメソッドの内容に変更を加える」際に利用します。
よって、親クラスのメソッドの新規追加・更新をすることができるのです。
一方、親クラスと子クラスのインスタンスを生成した場合は、
1 | (C) Oya o = new Ko(); |
親クラスのメソッドのみアクセスできて、且つ子クラスに同じメソッドがあれば、
子クラスのメソッドを優先するという仕組みですね。
言い換えれば、これはメソッドのオーバーライドを前提にしたインスタンスになります。
オーバーライドが発生しない場合、Aの親クラスのインスタンスと動作がほぼ同じですね。
なので、親クラスのメソッドの更新を行なうのがこのインスタンスの役割です。
1 | (D) Ko k = new Oya(); |
上記Dはエラーになります。
この記述方法は誤りで、親クラスのインスタンスをダウンキャストしてあげなければ動作しません。
大方この考えさえあれば継承クラスをマスターできると思います。
最新記事 by よっき (全て見る)
- 「圧着」と「圧接」の違い!コネクタを使った効率的な配線作業! - 2019年10月26日
- 夏の暑さ対策は大丈夫?冷却性能抜群のおすすめCPUクーラー!メモリに干渉しない最強の商品を紹介! - 2018年5月1日
- 自作PC弐号機のケースを換装!SilverStone製のミニタワーで冷却性とかっこよさを追求! - 2018年3月11日
スポンサードリンク