継承ベースのポリモーフィズムを調べる
継承ベースのポリモーフィズムは、派生クラスが基底クラスから動作とプロパティを継承するクラス階層に基づいています。 継承リレーションシップを使用すると、派生クラスのオブジェクトを基底クラスのオブジェクトとして扱います。 派生クラス オブジェクトを基底クラス オブジェクトとして扱うことができるので、コンパイル時に特定の型を知らなくても、複数の種類のオブジェクトで動作するコードを記述できます。
次のコード サンプルは、C# での継承ベースのポリモーフィズムを示しています。
// Base class
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound.");
}
}
// Derived class Dog
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
// Derived class Cat
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cat meows.");
}
}
// Derived class Cow
public class Cow : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cow moos.");
}
}
class Program
{
static void Main()
{
// Create an array of Animal objects
Animal[] animals = new Animal[3];
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Cow();
animals[0] = animal1;
animals[1] = animal2;
animals[2] = animal3;
// Demonstrate polymorphism
foreach (Animal animal in animals)
{
animal.MakeSound();
}
}
}
このサンプル コードでは、Program クラスが Animal オブジェクトの配列を作成し、Dog、Cat、および Cow のインスタンスを配列要素に割り当てることに注意してください。
MakeSound メソッドは配列内の各オブジェクトで呼び出され、ポリモーフィズムが示されます。
MakeSound メソッドは、各動物の種類に固有の動作を提供するために、派生クラスでオーバーライドされます。
基底クラスのオブジェクトを派生クラスにキャストする
C# でのキャストは、ある型のオブジェクトを別の型に変換するプロセスです。 キャストは、基底クラスと 1 つ以上の派生クラスがある継承階層を使用してポリモーフィズムを実装するときによく使用されます。
キャストには主に次の 2 種類があります。
暗黙的キャスト: これは、派生クラスを基底クラスに変換するときに自動的に発生します。 派生クラスのすべてのインスタンスも基底クラスのインスタンスであるため、安全です。
BankAccount account = new CheckingAccount();明示的キャスト: これにはキャスト演算子が必要であり、基底クラスを派生クラスに変換するときに使用されます。 基底クラスのすべてのインスタンスが派生クラスのインスタンスであるとは限らないため、常に安全であるとは限りません。
CheckingAccount checkingAccount = (CheckingAccount)account;
is キーワードと as キーワードを使用してオブジェクトをキャストする
C# では、 is キーワードと as キーワードを使用してオブジェクトをキャストできます。 これらのキーワードは、オブジェクトを別の型にキャストする前に、オブジェクトの型をチェックする安全な方法を提供します。 C# でオブジェクトをキャストする一般的な方法を次に示します。
パターン マッチングで
isキーワードを使用する:if (account is CheckingAccount checkingAccount) { // Use checkingAccount as a CheckingAccount }- この構文では、
accountがCheckingAccount型であるかどうかを確認します。 - チェックが成功すると、
accountがCheckingAccountにキャストされ、変数checkingAccountに割り当てられます。 - この方法は、型チェックとキャストを 1 つの手順で組み合わせた簡潔で安全です。
- この構文では、
isキーワードを使用し、その後に明示的なキャストを行います。if (account is CheckingAccount) { CheckingAccount checkingAccount = (CheckingAccount)account; // Use checkingAccount as a CheckingAccount }- この構文では、
accountがCheckingAccount型であるかどうかを確認します。 - チェックが成功した場合、
accountを明示的にCheckingAccountにキャストし、変数checkingAccountに割り当てます。 - この方法はパターン マッチング構文よりも詳細ですが、キャスト プロセスをより詳細に制御できます。
- この構文では、
asキーワードの使用:CheckingAccount checkingAccount = account as CheckingAccount; if (checkingAccount != null) { // Use checkingAccount as a CheckingAccount }- この構文は、
accountをCheckingAccountにキャストしようと試み、結果をcheckingAccountに割り当てます。 - キャストが成功した場合、
checkingAccountにはキャスト オブジェクトが含まれます。それ以外の場合は null です。 - この方法は、キャスト オブジェクトを使用する前にキャスト結果を確認する場合に便利です。 たとえば、例外を回避し、エラーケースを適切に処理する場合です。
- この構文は、
キャストを実装する場合は、次のガイドラインを考慮してください。
-
isでのパターン マッチングの使用: 型チェックとキャストを 1 つのステップで組み合わせます。 - 明示的なキャストで
isキーワードを使用する: 型チェックを分離して 2 つのステップにキャストし、キャスト プロセスをより詳細に制御します。 -
asキーワードの使用: null を返すことによってキャストを試行し、エラーを適切に処理します。
-
これらのキャスト手法を理解することは、C# でポリモーフィズムと継承を操作するために不可欠です。
ポリモーフィズムを実装するときの一般的な落とし穴を避ける
目的が継承ベースのポリモーフィズムである場合は、回避すべき事項と、確認すべき点をいくつか次に示します。
シールされたクラスとメソッドの使用を避ける: Sealed クラスとメソッドは継承またはオーバーライドできないため、ポリモーフィズムを使用する機能が制限されます。 クラスまたはメソッドをシールすると、それ以上の拡張とカスタマイズは行われなくなります。 例えば:
public sealed class BankAccount { } // This class can't be inherited静的メソッドの過剰使用を避けます。 静的メソッドは、クラスのインスタンスではなく、クラス自体に属します。 これらはオーバーライドできません。つまり、多型に参加しません。
public static void PrintMessage() { } // This method can't be overridden緊密な結合を避けます。 厳密な結合は、システム内のクラスまたはコンポーネントが相互に大きく依存している場合に発生します。 つまり、あるクラスの変更が他のクラスに直接影響を与える可能性があり、システムの柔軟性が低下し、保守が困難になります。 厳密な結合は、コードのテスト、拡張、変更が困難になることがあります。
public class BankAccount { public void TransferFunds(SavingsAccount savingsAccount) { // Tight coupling with SavingsAccount } }'new' キーワードは、適切な理由なしで使用しないでください。 'new' キーワードは、派生クラスの基底クラス メソッドを非表示にするため、混乱や予期しない動作につながる可能性があります。 基底クラスメソッドを意図的に非表示にする場合にのみ、'new' キーワードを使用してください。
public class Dog : Animal { public new void MakeSound() // Hides the base class method. Better to use 'override' { Console.WriteLine("The dog barks."); } }一貫性のあるメソッド シグネチャを確認します。 派生クラスでオーバーライドされたメソッドのシグネチャが基底クラス メソッドと同じであることを確認します。 メソッド シグネチャを変更すると、オーバーライドするのではなく、メソッドが非表示になります。
public class Animal { public virtual void MakeSound(string sound) { Console.WriteLine("The animal makes a sound."); } } public class Dog : Animal { // Method signature doesn't match the base class public override void MakeSound() { Console.WriteLine("The dog barks."); } }
概要
C# の継承ベースのポリモーフィズムを使用すると、派生クラスが基底クラスから動作とプロパティを継承するクラスの階層を作成できます。 この継承メカニズムを使用すると、派生クラスのオブジェクトを基底クラスのオブジェクトとして扱います。 派生クラス オブジェクトを基底クラスのメンバーとして扱う機能を使用すると、コンパイル時に特定の型を知らなくても、複数の種類のオブジェクトで動作するコードを記述できます。 キャスト手法を理解し、一般的な落とし穴を回避し、ベスト プラクティスに従うことで、C# アプリケーションでポリモーフィズムを効果的に実装できます。