クラス継承の原則を調べる
継承は、オブジェクト指向プログラミングの主な特性の 1 つです。 これにより、クラス間のリレーションシップを定義することで、クラスの階層を作成できます。 C# では、共通の動作と特性を定義する基底クラスを作成し、その動作を継承して拡張する派生クラスを作成できます。
たとえば、Person という名前の基底クラスでは、Name プロパティと Age プロパティを定義できます。
Employee という名前の派生クラスは、これらのプロパティを継承し、EmployeeNumber や Salaryなどの他のプロパティを定義できます。
この例は、次の C# コードを使用して表されます。
public class Person
{
public string? Name { get; set; }
public int Age { get; set; }
}
public class Employee : Person
{
public int EmployeeNumber { get; set; }
public decimal Salary { get; set; }
}
このコード サンプルでは、Person クラスと Employee クラスを定義します。
: クラス宣言のコロン (Employee) 文字に注目してください。
: と Employee の間のコロン (Person) は、Employee クラスが Person クラスから継承されることを示します。 この場合、Employee クラスは Name プロパティと Age プロパティを継承し、さらに 2 つのプロパティ (EmployeeNumber と Salary) を定義します。
Employee オブジェクトを作成すると、Name クラスで定義されている Age プロパティと Person プロパティ、および EmployeeNumber クラスで定義されている Salary プロパティと Employee プロパティにアクセスできます。
Person オブジェクトを作成すると、Name および Age プロパティにのみアクセスできます。
継承を使用すると、共通の動作と特性を共有するクラスの階層を作成できます。 これにより、コードを再利用し、クラス間のリレーションシップを定義できます。 継承を使用すると、保守性が高く拡張可能なコードを作成できます。
継承の利点
継承には、次のようないくつかの利点があります。
- Code reuse: 継承を使用すると、派生クラスの基底クラスで定義されたコードを再利用できます。 これにより、重複が減り、コードの再利用が促進されます。
- 機能拡張: 継承を使用すると、派生クラスに新しいメンバーを追加することで、基底クラスの動作を拡張できます。 派生クラスでは、新しいプロパティ、メソッド、およびイベントを定義できます。
- カプセル化: 継承では、基底クラスの実装の詳細を派生クラスから非表示にできるため、カプセル化が促進されます。 継承とカプセル化を使用すると、派生クラスのオブジェクトと対話するための明確なインターフェイスを定義できます。
- 整合性: 継承では、基底クラスで一般的な動作を定義できるため、整合性が促進されます。 基底クラスから継承すると、派生クラスが同じ基本動作を共有できます。
- ポリモーフィズム: 継承によりポリモーフィズムが有効になり、派生クラスのオブジェクトを基底クラスのオブジェクトとして扱うことができます。 ポリモーフィズムを使用すると、コンパイル時に特定の型を知らなくても、異なる型のオブジェクトで動作するコードを記述できます。
クラスの継承とインターフェイスの実装を比較する
C# には、クラス間のリレーションシップを定義するための 2 つのメカニズム (クラスの継承とインターフェイスの実装) が用意されています。 クラス継承を使用すると、クラスは基底クラスからメンバーを継承できます。一方、インターフェイスの実装では、クラスがインターフェイスで定義されているメンバーを実装できます。 どちらのメカニズムもコードの再利用を可能にし、ポリモーフィズムを促進しますが、特性は異なります。
クラスの継承には、次の特性があります。
- クラスは、1 つの基底クラスからのみ継承できます。
- 派生クラスは、基底クラスで定義されている動作を再利用、拡張、および変更できます。
- 継承により、クラス間に "is-a" リレーションシップが作成されます。
インターフェイスの実装には、次の特性があります。
- クラスは複数のインターフェイスを実装できます。
- クラスは独自の動作を定義し、インターフェイスで定義されたメンバーを実装できます。
- インターフェイスの実装では、クラス間に "can-do" リレーションシップが作成されます。
オブジェクト指向システムを設計する場合、"is-a" と "can-do" のリレーションシップの違いは重要です。 一般に、派生クラスが基底クラスの特殊なバージョンである場合は、クラス継承を使用する必要があります。 クラスが特定の一連のアクションを実行できる場合は、インターフェイス実装を使用する必要があります。
クラスの継承を使用する場合の例として、Dog という名前の基底クラスと、German Shepherd および Golden Retrieverという名前の派生クラスがある場合があります。
German Shepherd と Golden Retriever は、Dogの特殊なバージョンです。 この場合、クラス継承を使用して、Dog クラス内のプロパティとメソッドの共通セットを定義し、German Shepherd クラスと Golden Retriever クラスでその動作を拡張および変更できます。
インターフェイス実装を使用する場合の例として、IDrawable メソッドを定義する Draw という名前のインターフェイスがある場合があります。
IDrawable や Circleなど、描画できるクラスに Rectangle インターフェイスを実装できます。 この場合、インターフェイスの実装を使用して、さまざまなクラスで共有される一般的なアクションのセットを定義できます。
クラスの継承とポリモーフィズムの比較
クラスの継承とポリモーフィズムは、オブジェクト指向プログラミングにおける密接に関連する概念です。 継承を使用すると、共通の動作を共有するクラスの階層を定義できますが、ポリモーフィズムを使用すると、派生クラスのオブジェクトを基底クラスのオブジェクトとして扱うことができます。
たとえば、HousePet という名前の基底クラスと、Dog および Catという名前の派生クラスについて考えてみます。
HousePet クラスは、ペットが行うサウンドを表す文字列を返す Speak メソッドを定義します。
Dog クラスは Speak メソッドをオーバーライドして "Woof" を返し、Cat クラスは Speak メソッドをオーバーライドして "Meow" を返します。 Dog 型または Cat 型の myPet という名前の HousePet オブジェクトを作成し、Speak メソッドを呼び出して適切な応答を取得できます。
この例では、HousePet クラスは、Speak クラスと Dog クラスが共有する一般的な Cat 動作を定義します。
Dog クラスと Cat クラスは、Speak メソッドをオーバーライドして動作をカスタマイズします。 派生クラスの 1 つを参照する Speak オブジェクトに対して HousePet メソッドを呼び出すと、オブジェクトの型に基づいて適切な応答が返されます。 この概念を示すコード サンプルを次に示します。
HousePet myPet1 = new Dog(); // Create a HousePet object named myPet1 that's of type Dog
HousePet myPet2 = new Cat(); // Create a HousePet object named myPet2 that's of type Cat
Console.WriteLine(myPet1.Speak()); // Call the Speak method on myPet1
Console.WriteLine(myPet2.Speak()); // Call the Speak method on myPet2
// Output: Woof
// Meow
public class HousePet
{
public virtual string Speak()
{
return "Hello";
}
}
public class Dog : HousePet
{
public override string Speak()
{
return "Woof";
}
}
public class Cat : HousePet
{
public override string Speak()
{
return "Meow";
}
}
ポリモーフィズムを使用すると、コンパイル時に特定の型を知らなくても、異なる型のオブジェクトで動作するコードを記述できます。 この例では、ポリモーフィズムは、HousePet 型または Dog型の Cat クラスのインスタンスを作成することによって実現されます。
Speak メソッドは、HousePet オブジェクトに対して呼び出され、"Woof" または "Meow" のいずれかのオブジェクトの型に基づいて適切な応答が返されます。 C# では、クラス継承またはインターフェイス実装を使用してポリモーフィズムを実現できます。
概要
継承はオブジェクト指向プログラミングの基本的な概念であり、クラス間のリレーションシップを定義することでクラスの階層を作成できます。 C# では、クラス継承を使用して、一般的な動作と特性を定義する基底クラスを作成し、その動作を継承して拡張する派生クラスを作成できます。 継承には、コードの再利用、拡張性、カプセル化、一貫性、ポリモーフィズムなど、いくつかの利点があります。 継承を使用すると、保守性が高く拡張可能なコードを作成できます。