「こんにちは、アミーゴ! さて、ここであなたがよく使うと思うトピックを紹介します。私は継承について話しています。

初心者にとって、プログラミングは魔法のようなものです。それでは、たとえ話から始めましょう…

あなたが空飛ぶ馬を作りたい魔術師だとしましょう。ペガサスを召喚してみるのもいいかもしれません。しかし、空飛ぶ馬は自然に発生するものではないので、非常に苦労することになります。やるべきことがたくさんあるでしょう。馬から始めて翼を召喚する方がはるかに簡単です。

継承。 継承のメリット - 1

プログラミングでは、このプロセスを «継承» と呼びます。非常に複雑なクラスを作成する必要があるとします。コードを最初から作成するのに長い時間を費やし、その後、バグを見つけるために長時間のテストを実行する可能性があります。しかし、なぜそれを難し​​い方法で行うのでしょうか?周りを見回して、探しているクラスがすでに存在するかどうかを確認したほうがよいでしょうか?

必要な機能の 80% を実装するクラスを見つけたとしましょう。そのコードをクラスにコピーするだけです。しかし、それにはいくつかの欠点があります。

1) 見つかったクラスは、すでにバイトコードにコンパイルされている可能性があります。ソースコードにアクセスできない可能性があります。

2) あなたはクラスのソース コードを持っているかもしれませんが、他人のコードを 6 行でも使用すると数十億で訴えられる可能性がある会社に勤めていることもあります。そして、彼らはあなたを訴訟するでしょう。

3) これにより、多くのコードが不必要に重複することになります。そして、他のクラスの作成者がバグを見つけて修正したとしても、依然としてバグが残っていることになります。

元のクラスのコードに対する法的許可を取得する必要のない、より洗練されたソリューションがあります。Java では、他のクラスを自分のクラスの親として宣言するだけで済みます。これは、そのクラスのコードを独自のクラスに追加することと同じです。親クラスのすべてのデータとメソッドがクラスに表示されます。たとえば、«馬» を継承し、«翼» を追加して、«ペガサス» を取得できます。

継承。 継承のメリット - 2

「とても興味深いです。続けてください。」

「継承には他の用途もあります。非常によく似た 10 個のクラスがあるとします。それらは一致するデータとメソッドを持っています。特別な基本クラスを作成し、データ (および関連するメソッド) を基本クラスに移動し、それらの 10 個のクラスを持つことができます。つまり、クラスごとに、基本クラスとも呼ばれる親クラスがあることを示します。

「抽象化の利点がカプセル化に関連してのみ真に明らかになるのと同じように、継承の利点はポリモーフィズムによってさらに大きくなります。しかし、それについては明日お話しします。今日は継承の例をいくつか見てみましょう。」

「チェス プログラムを書いているとします。チェスの駒のクラスが必要になります。アミーゴ、どのクラスをお勧めしますか?」

「キング、クイーン、ビショップ、ナイト、ルーク、ポーン。」

「とてもよかったです。何も見逃していませんでした。」

「そして、これらのクラスにどのようなデータを保存することをお勧めしますか?」

「各駒のボード位置 (x と y) と価値。結局のところ、一部の駒は他の駒よりも価値があります。」

「そして、これらのクラスの違いは何ですか?」

「彼らは駒の動かし方や振る舞いが違うのです。」

「はい。次のようにクラスとして定義できます。」

class King
{
int x;
int y;
int worth;
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen
{
int x;
int y;
int worth;
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook
{
int x;
int y;
int worth;
void rookMove()
{
//code that defines,
//how the rook moves
}
}
class Knight
{
int x;
int y;
int worth;
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop
{
int x;
int y;
int worth;
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn
{
int x;
int y;
int worth;
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

「はい、まさにそのように書きます。」

「しかし、継承を使用してコードの記述量を減らす方法を見てください。同一のメソッドとデータを共通のクラスに移動できます。それを ChessItem と呼びましょう。ChessItem オブジェクトを作成するのは意味がありません。それらはどのオブジェクトにも対応しないためです。チェスの駒ですが、このクラスは非常に役立ちます。」

class King extends ChessItem
{
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen extends ChessItem
{
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook extends ChessItem
{
void rookMove()
{
//code that defines,
//how the rook moves
}
}
 class ChessItem
{
int x;
int y;
int worth;
}
 
class Knight extends ChessItem
{
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop extends ChessItem
{
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn extends ChessItem
{
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

"なんて面白い!"

「その通りです。その利点は、数千の異なるオブジェクトと数百のクラスを含むプロジェクトで特に大きくなります。この場合、クラスを適切に選択すると、ロジックが大幅に簡素化されるだけでなく、必要なコードを 10 分の 1 に減らすことができます。」

「では、クラスを継承するにはどうすればよいでしょうか?」

"クラスを宣言した後、キーワード ' extends ' を使用し、その後に親クラスの名前を続けます。継承できるクラスは 1 つだけです。 "

継承。 継承のメリット - 3

写真は《豚》から受け継いだ「牛」です。「豚」は「鶏」から継承し、「鶏」は「卵」から継承します。各クラスの保護者は 1 人だけです。このような継承は必ずしも論理的であるとは限りません。ブタしかいないが、本当にウシが必要な場合、プログラマはしばしば「ブタ」から「ウシ」を作りたいという欲求に抗えなくなります。

「しかし、2 つのクラスを継承したい場合はどうすればよいでしょうか? 何かできることはありますか?!」

「そうではありません。Java クラスは実装の多重継承をサポートしていません。クラスは親クラスを 1 つしか持つことができません。しかし、型の多重継承は存在します。つまり、クラスは複数のインターフェイスを実装できます。これにより、問題はわずかに軽減されます。 」

「なるほど。それでインターフェースって何ですか?」

「インターフェイスについては明日説明します。今のところは継承について掘り下げていきましょう。」