Java はオブジェクト指向言語です。これは、Java のすべてがクラスとそのオブジェクトで構成されており、OOP (オブジェクト指向プログラミング) のパラダイムに従っていることを意味します。そのようなパラダイムの 1 つは継承です。これは、あるクラスが別のクラスの機能 (フィールドとメソッド) を継承できるようにする Java のメカニズムです。簡単に言うと、Java では、継承とは、既存のクラスに基づいて新しいクラスを作成することを意味します。

Java における継承の主要な主体
- 継承とは、クラスがその親 (継承元のクラス) のプロパティとメソッドを部分的または完全に繰り返すことができるという概念です。
- 子クラス、サブクラス、拡張クラス、派生クラスは、別のクラスを継承するクラスです。
- 親クラス、スーパークラス、基底クラスとは、多数の関数を持ったクラスであり、これらの関数は他のクラス(子クラス)に受け渡す(継承する)ことができます。
- メソッドのオーバーライドとは、派生クラス メソッドの動作を変更することです。これは通常、より具体的で洗練された動作です。親クラスに既に存在する継承メソッドをオーバーライドすると、そのメソッドは親メソッドを置き換えるようになります。
- クラスは祖先クラスを 1 つだけ持つことができますが、各クラスは多数の「子」を持つことができます。
使い方
継承チェーンは、最も抽象的なクラスからより具体的なクラスへと方向付けられます。つまり、スーパークラスはクラスのチェーンの中で最も抽象的なクラスです。多くの場合、これは抽象 (実装を必要としない基本クラス) として示されます。それ以降のクラスはすべて、より具体的になります。たとえば、「ガジェット」というクラスがあります。これには、フィールド (または状態) の「重量」フィールドバッテリー容量、フィールド充電レベル、および「作業」および充電方法 (または動作) を含めることができます。この場合、メソッドは抽象的になる可能性があります。つまり、メソッドには特定の実装がありません。それがどのようなガジェットであるかは言えませんが、間違いなく充電可能なガジェットです。Gadget クラスの Phone サブクラスを作成しましょう。重量とバッテリーを再定義する必要はなくなり、抽象ガジェットからそれらを継承するだけです。ただし、作業の動作を明確にする必要があります。他のフィールド「画面の対角線」やコネクタなどを追加することもできます。新しい方法「オペレーティング システムの更新」を追加できます。次に、さらに 2 つのクラスを作成できます。両方とも Phone、Android、iPhone から継承されます。どちらのクラスもガジェットとスマートフォンのすべてのフィールドとメソッドを継承しており、メソッドはオーバーライドできます。ファースト クラスには「ブランド名」フィールドが必要ですが、iPhone ではそのようなスマートフォンを製造しているのは 1 社だけであるため、このフィールドは必要ありません。
class Gadget {
…
}
}
//subclass of Gadget class
class Phone extends Gadget {
…
}
//subclass of Phone class
class IPhone extends Phone {
…
}
//subclass of Phone class
class AndroidPhone extends Phone {
…
}
子クラスは、親クラスのすべての public メンバーと protected メンバーを継承します。サブクラスがどのパッケージ内にあるかは関係ありません。子クラスが親クラスと同じパッケージ内にある場合、子クラスは親の package-private メンバーも継承します。継承されたメンバーをそのまま使用したり、置換したり、非表示にしたり、新しいメンバーを追加したりできます。
- 他のフィールドなど、継承されたフィールドを直接使用できます。
- 親クラスと同じ名前のフィールドを子クラスで宣言できます。それを隠している(だからやらないほうがいい)。
- 子クラスで新しいフィールド (親クラスにないフィールド) を宣言できます。
- 継承されたメソッドは、派生クラスでオーバーライドすることなく直接使用できます。
- また、親クラスのメソッドと同じシグネチャを持つ新しいインスタンス メソッドをサブクラスに作成することもできます。このプロシージャはそれをオーバーライドします。
- 親クラスで宣言されていない新しいメソッドを子クラスで宣言できます。
- 暗黙的または super キーワードを使用してスーパークラス コンストラクターを呼び出すサブクラス コンストラクターを作成できます。
例
重みフィールドと商標フィールド、およびwork()メソッドを備えた基本 MusicalInstrument クラスを作成しましょう。コンストラクターも定義します。
public class MusicalInstrument {
int weight;
String tradeMark;
public MusicalInstrument(int weight, String tradeMark) {
this.weight = weight;
this.tradeMark = tradeMark;
}
public void work() {
System.out.println("the instrument is playing...");
}
}
何の楽器なのか、どうやって演奏するのか全く不明。より具体的な楽器、バイオリンを作成してみましょう。これには、Musical Instrument と同じフィールドが含まれます (フィールドは、super キーワードを使用してコンストラクターで呼び出されます。作業メソッドをオーバーライドして、バイオリンの弦を 1 つずつ設定するメソッドを作成することもできます。
public class Violin extends MusicalInstrument {
String master;
String owner;
int age;
boolean isTuned;
public Violin(int weight, String tradeMark, String master, String owner, int age, boolean isTuned) {
super(weight, tradeMark);
this.master = master;
this.owner = owner;
this.age = age;
this.isTuned = isTuned;
}
@Override
public void work() {
System.out.println("THe violin's playing");
}
public void violinTuning () {
System.out.println("I'm tuning 1st string...");
System.out.println("I'm tuning 2nd string...");
System.out.println("I'm tuning 3rd string...");
System.out.println("I'm tuning 4th string...");
}
}
ViolinクラスをテストするためのDemoクラス を作成し、継承がどのように機能するかを正確に確認してみましょう。
public class InheritDemo {
public static void main(String[] args) {
Violin violin = new Violin(1, null, "Amati", "Kremer", 285, false);
violin.violinTuning();
violin.work();
}
}
この場合、プログラムの出力は次のようになります。
1 弦をチューニングしています... 2 弦をチューニングしています... 3 弦をチューニングしています... 4 弦をチューニングしています... ヴァイオリンが演奏しています
つまり、子クラスにオーバーライドされたメソッドがある場合、祖先メソッドは呼び出されなくなります。そこにない場合はどうなりますか? つまり、Violin クラスは次のようになります。
public class Violin extends MusicalInstrument {
String master;
String owner;
int age;
boolean isTuned;
public Violin(int weight, String tradeMark, String master, String owner, int age, boolean isTuned) {
super(weight, tradeMark);
this.master = master;
this.owner = owner;
this.age = age;
this.isTuned = isTuned;
}
// @Override
// }
public void violinTuning () {
System.out.println("I'm tuning 1st string...");
System.out.println("I'm tuning 2nd string...");
System.out.println("I'm tuning 3rd string...");
System.out.println("I'm tuning 4th string...");
}
}
出力は次のとおりです。
1弦をチューニングしています... 2弦をチューニングしています... 3弦をチューニングしています... 4弦をチューニングしています... 楽器が鳴っています...
つまり、祖先メソッドが自動的に呼び出されます。ちなみに、子クラスは祖先を通じて定義できます。つまり、アップキャストを実行します。
Parent parent = new Child()
この初期化は、親クラスに存在するメンバーとオーバーライドされたメソッドのみにアクセスするために使用されます。この例では次のようになります。
public class InheritDemo {
public static void main(String[] args) {
MusicalInstrument violin = new Violin(1, null, "Amati", "Kremer", 285, false);
//violin.violinTuning();
violin.work();
}
}
この場合、バイオリンメソッドを設定することはできません。ただし、同時に、子孫クラスの work()メソッドが存在する場合には呼び出されます。
Java プラットフォームのクラス階層
Java では、すべてがクラスで構成され、クラスは階層に従属します。他のすべてのクラスが継承されるクラスは存在するのでしょうか?という疑問が生じます。答えは「はい」です。確かにそのようなクラスは存在します。そしてそれは単にObjectと呼ばれます。java.lang パッケージの Object クラスは、作成したクラスを含むすべてのクラスに共通の動作を定義および実装します。Java プラットフォームでは、多くのクラスがObjectから直接派生し、他のクラスはこれらのクラスの一部から派生するなど、クラス階層を形成します。Java における継承の種類
Java の継承のいくつかのタイプに焦点を当ててみましょう。1. 単一継承 このタイプは、上記の例と同様に、サブクラスが 1 つのスーパー クラスの機能を継承します。以下の図では、クラス A が派生クラス B の基本クラスとして機能します。 2. 多レベルの継承 これは単なる継承の連鎖です。つまり、基本クラス A があり、クラス B がそこから継承され、クラス C が継承されます。 Java では、クラスは祖父母のメンバーに直接アクセスできません。3. 階層的継承 階層的継承では、1 つのクラスが複数のサブクラスのスーパークラス (基本クラス) として機能します。上では、AndroidPhone と IPhone という 2 つの「子」を持つことができる Phone クラスの例を示しました。
class A {
public void printA() {
System.out.println("A");
}
}
class B extends A {
public void printB() {
System.out.println(" B"); }
}
class C extends A {
public void printC() {
System.out.println("C");
}
}
class D extends A {
public void printD() {
System.out.println("D");
}
}
public class Demo {
public static void main(String[] args)
{
B objB = new B();
objB.printA();
objB.printB();
C objC = new C();
objC.printA();
objC.printC();
D objD = new D();
objD.printA();
objD.printD();
}
}
出力は次のとおりです。
ABCAD
4. 多重継承、つまり複数の祖先の存在 ... ただし、待ってください。古典的な多重継承は Java ではサポートされていません。ある程度までは、クラスではなくインターフェイスを使用して実装できます。
interface A {
public void printA();
}
interface B {
public void printB();
}
interface C extends A, B {
public void print();
}
class InheritDemo implements C {
@Override
public void print()
{
System.out.println("Print something");
}
@Override
public void printA() {
}
@Override
public void printB() {
}
}
GO TO FULL VERSION