第 2 章 Java 言語の基本的な文法 I 5
3.32 WeightedPoint.java ( 重み付きの点クラス )
継承は連鎖的に行うことができます。つまり、クラスAがクラスBを継承し、そのクラスBが新たなクラスCを 継承するような状況です(図3.5参照)。このとき、クラスAのインスタンスを作成すると、そこには、クラスAで宣 言されたフィールドa(やメソッド)はもちろんのこと、クラス Bのフィールドb、クラスCで宣言されたフィール
ドcを持つことになります。
右の図は、クラスA のインスタンス instAを作成したときの概念的な図です。instA は、クラスA のインスタ ンスですから、フィールド aをもちろん持ちますが、クラス Bを継承しているので、フィールドb も持ち、同様に フィールドcも持つわけです。
A + a : int
B + b : int
C + c : int
int a
int b
int c
クラスBから 継承した部分
クラスCから 継承した部分 instA
クラスAのインスタンス型
図3.5 単一継承
クラス Cをスーパークラスとするクラスは、クラスBだけとは限りません。先に「人」クラスを「学生」クラスと
「教授」クラスが継承しましたよね。しかし、複数のスーパークラスを持つこと「多重継承(multiple inheritance)」は Javaでは許されていません。と言うか、ほとんどのオブジェクト指向言語は、多重継承を許していません (C++は許し ている)。Java のように多重継承を許さない継承方式を「単一継承(single inheritance)」方式と言います。
何か不便な気がする? そうですね。例えば、「水陸両用車」クラスと考えるとき、「自動車」と「船」の2つのクラス を定義して継承するのが順当な気がする。「電子ピアノ」は「ピアノ」と「電化製品」。「狼人間」は「狼」と「人間」。
これらができないJavaはC++に負けてる?
なぜJavaは単一継承を選択しているのでしょう。それを示す例が次のプログラムです。
ソースコード3.33 単一継承の理由 // 水陸両用車クラスが2つのクラスを継承できるとする
class AmphibiousCycle extends Car, Boat {
// どちらの speed と drive() を継承したら良いのでしょう?
}
class Car { // 自動車クラス double speed; // 単位 km/h
void drive() { ・・・} // 陸上をタイヤで運転 }
class Boat { // 船クラス
double speed; // 単位 knot : 1knot = 1852m/h void drive() { ・・・} // 水上をスクリューで運航 }
多重継承を許すと、継承する2 つのスーパークラスに同じフィールドや同じメソッドが存在したら、サブクラスはその いずれを選択すべきか?の問題が生じます。また、同じクラスを重複して継承する問題も生じます (自動車のスーパー
クラスとしての乗り物クラスと船のスーパークラスとしての乗り物)。これらの問題を「菱形継承問題もしくはダイア モンド継承問題」と呼びます。
自動車 船
乗り物
drive()
drive() drive()
水陸両用車 drive()
図3.6 菱形継承問題
C++はそうした選択をプログラマに任せている(明にプログラム中で選ぶ)のですが、Java などはその危険性(プロ グラマを信じていない?)を重要視し、こうした多重継承を許していません。その代わりに、後で出てきます「インタ フェース」という「クラスもどき?」を用いて単一継承の不便さを解消しています。
なお、「スーパークラス・サブクラス」という言葉は、直接継承関係にある2つのクラス間の呼び方なので、クラスA からクラスCを見るとき、本来「スーパークラスのさらにスーパークラス」と言わないといけません。これはちょっ と不便なので、直接の継承関係になくとも、何段階かの継続関係にあるクラスの間で誤解が生まれない限り、このテキ ストでは「スーパークラス・サブクラス」の言葉を流用するか、ここだけの言葉として、「お爺さんのクラス・孫のクラ ス」などとよぶことにします。つまり、クラスCはクラスAのお爺さんクラスで、クラスA はクラスCの孫クラス である!と(孫のほうが一般に機能が多い!?)。
問題 3.4.2. 次の(a),(b),(c)のうち単一継承はどれですか。
A + a : int
B + b : int C
+ c : int
A + a : int
B + b : int C
+ c : int
A + a : int
B + b : int C
+ c : int
D + d : int
(a) (b) (c)
問題 3.4.3. 左のような継承関係のとき、そのいずれかのクラスのインスタンスを書いたのが右の図である。下線部に 適当なクラス名を入れ、3つのクラス内のフィールド名とメソッド名を右の図の妥当な場所に書き込みなさい。
A + x : double + y : double + length() : double
B + w : double
+ getWeight() : double
C + c : java.Color + getColor() : java.Color
クラス のインスタンス クラス の情報
クラス の情報