Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
学ぶ Polymorphism | OOP原則
C#オブジェクト指向構造

bookPolymorphism

メニューを表示するにはスワイプしてください

**ポリモーフィズム(多態性)**という用語は、「複数の異なる形で現れること」を意味します。オブジェクト指向プログラミングの文脈では、ポリモーフィズムは、クラスが派生クラスに共通のインターフェースを提供しつつ、それぞれの派生クラスが継承したメソッドに対して固有の動作を実装できる能力を指します。

通常、クラスのオブジェクトを作成する際には、そのオブジェクトの参照を保持する変数を作成します。そして、その変数の型は通常、そのオブジェクトのクラスになります。

例:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

しかし、基底クラスの変数を作成し、その中に派生クラスのオブジェクトを格納することもできます。

例:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

Dogオブジェクトのbreed属性はアクセスできません。なぜなら、DogオブジェクトをMammal変数に格納すると、自動的に変換されMammal型になるためです。つまり、Mammalクラスに存在する属性やメソッドのみがアクセス可能となります。breedクラスに格納された値が失われるわけではなく、単にアクセスできなくなり、本質的には隠されている状態です。

明示的な型変換(キャスト)を使ってexampleDog型に変換すれば、breed属性に再びアクセスできるようになります。

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

しかし、メソッドには メソッドのオーバーライド という追加機能があり、これは メソッドのオーバーロード とやや似ています。この場合、基本クラスのメソッドを派生クラスで再定義します。

例えば、Mammalspeak() メソッドを持たせ、Woof! オブジェクトから呼び出された場合は DogMeow! オブジェクトから呼び出された場合は Cat を出力するようにしたい場合があります。

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

このコンパイル時に表示される警告は、親クラスと子クラスでメソッド名が重複しているために発生します。この場合、speak クラスと Cat クラスの Mammal メソッド、また Dog クラスと Mammal クラスの間で重複があるため、2つの警告が表示されます。

ただし、最後に m1m2m3Mammal クラスで定義されたメソッドを実行していることに注目してください。これは、それらが Mammal オブジェクトとしてキャストされているためです。

もし speak メソッドを元のオブジェクトの型に応じて動作させたい場合は、単純にそれを 仮想メソッド(virtual method) に変更できます。仮想メソッド とは、派生クラスからオーバーライドできるメソッドであり、実行時に元のオブジェクトの型に基づいて特定の実装が決定されます。

メソッドを仮想にするには、戻り値の型の前に virtual キーワードを追加します。

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

このメソッドのオーバーライド実装を作成するには、派生クラスで新しいバージョンを実装する際に、戻り値の型の前にキーワード override を使用します。

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

それでは、2つのコードスニペットを組み合わせて、出力にどのような影響があるかを確認します。

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

出力結果を見ると、m2m3CatDog のメソッド実装を使用しています。これは、それらのオブジェクトが元々 CatDog であったためです。 このように、元の型に基づいてメソッドの動作を上書きする仕組み全体を ポリモーフィズム(多態性) と呼びます。

この機能が非常に役立つ場面の一つは、異なるデータ型のオブジェクトを1つの配列やリストに格納できることです。

例:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. メソッドのオーバーライドで使用される2つのキーワードは何ですか?

2. メソッドをオーバーライド可能にする正しい方法はどれですか?

question mark

メソッドのオーバーライドで使用される2つのキーワードは何ですか?

正しい答えを選んでください

question mark

メソッドをオーバーライド可能にする正しい方法はどれですか?

正しい答えを選んでください

すべて明確でしたか?

どのように改善できますか?

フィードバックありがとうございます!

セクション 5.  4

AIに質問する

expand

AIに質問する

ChatGPT

何でも質問するか、提案された質問の1つを試してチャットを始めてください

セクション 5.  4
some-alt