複数のインターフェース
CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 27/70。
クラスは1つの基底クラスからしか継承できませんが、必要に応じていくらでもインターフェースを実装することができます。これは、インターフェースが抽象クラスに対して持つ主な利点の1つであり、クラスが複数の振る舞いを取り入れることを可能にします。
複数のインターフェースを実装するには、コロンの後にカンマで区切ってそれらを列挙するだけです:
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}Duckクラスは、両方のインターフェースのすべてのメンバーを実装する必要があります。これは現実世界のシナリオを自然にモデル化しています。アヒルは実際に飛ぶことも泳ぐこともできるため、両方の契約を満たすことは理にかなっています。
継承と複数のインターフェースを組み合わせる場合、基底クラスを最初に記述する必要があります:
public class Duck : Bird, IFlyable, ISwimmable
{
// Birdを継承し、両方のインターフェースを実装します
}この柔軟性により、複数のソースから振る舞いを構成することができます。Robot は IMovable、IChargeable、および ISpeakable を実装するかもしれません。各インターフェースは単一の機能を表しており、クラスは必要なものを正確に組み合わせて使用できます。
チャレンジ
簡単1つのクラスが複数のインターフェースを実装することで、どのように異なる機能を得ることができるかを示すスマートホームデバイスシステムを構築しましょう。制御可能であり、かつネットワーク接続機能を持つデバイスを作成します。
コードは以下の4つのファイルに分けて構成します:
IControllable.cs:SmartHome名前空間内にIControllableというインターフェースを定義します。このインターフェースは、電源のオン・オフが可能なデバイスを表します。TurnOn()とTurnOff()という2つのメソッドを宣言し、どちらも文字列(string)を返すようにしてください。INetworkConnected.cs:SmartHome名前空間内にINetworkConnectedというインターフェースを定義します。このインターフェースは、ネットワークに接続可能なデバイスを表します。文字列を返すConnect(string network)メソッドを宣言してください。SmartTV.cs:SmartHome名前空間内に、IControllableとINetworkConnectedの両方を実装するSmartTVクラスを定義します。このテレビは、Brandプロパティ(string)とScreenSizeプロパティ(int、インチ単位)を持つ必要があります。これら2つの値を受け取るコンストラクタを作成してください。すべてのインターフェースメソッドを以下のように実装します:TurnOn()は"{Brand} {ScreenSize}-inch TV is now ON"を返します。TurnOff()は"{Brand} {ScreenSize}-inch TV is now OFF"を返します。Connect(string network)は"{Brand} TV connected to {network}"を返します。
Program.cs: メインファイルで、入力値を使用してSmartTVオブジェクトを作成します。同じテレビオブジェクトを、具体的なSmartTV型、IControllable変数、およびINetworkConnected変数の3つの異なる変数型に格納することで、複数インターフェースの柔軟性を示してください。それぞれの参照を通じて適切なメソッドを呼び出し、使用しているインターフェースに基づいて同じオブジェクトがどのように異なる扱いを受けるかを示します。
以下の3つの入力を受け取ります:
- テレビのブランド名
- インチ単位の画面サイズ
- 接続するネットワーク名
出力は以下の形式で表示してください:
Via SmartTV:
{TurnOn() result}
{Connect(network) result}
Via IControllable:
{TurnOff() result}
Via INetworkConnected:
{Connect(network) result}例えば、入力が Samsung、55、HomeWiFi の場合、出力は以下のようになります:
Via SmartTV:
Samsung 55-inch TV is now ON
Samsung TV connected to HomeWiFi
Via IControllable:
Samsung 55-inch TV is now OFF
Via INetworkConnected:
Samsung TV connected to HomeWiFi同じ SmartTV オブジェクトが、異なるインターフェース参照を通じてどのようにアクセスされるかに注目してください。IControllable として格納されている場合は制御メソッドのみを呼び出すことができ、INetworkConnected として格納されている場合はネットワークメソッドのみを呼び出すことができます。これが複数のインターフェースを実装する力です。1つのクラスが複数の機能を獲得しながら、その使用方法において柔軟性を保つことができます!
チートシート
クラスは、コロンの後にカンマで区切ってリストすることで、複数のインターフェースを実装できます。
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}クラスは、すべてのインターフェースのすべてのメンバーを実装する必要があります。
継承と複数のインターフェースを組み合わせる場合、基底クラスを最初に記述する必要があります。
public class Duck : Bird, IFlyable, ISwimmable
{
// Inherits from Bird, implements both interfaces
}これにより、各インターフェースが単一の能力を表す形で、複数のソースから振る舞いを構成することが可能になります。
自分で試してみよう
using System;
using SmartHome;
class Program
{
public static void Main(string[] args)
{
// 入力を読み込む
string brand = Console.ReadLine();
int screenSize = Convert.ToInt32(Console.ReadLine());
string network = Console.ReadLine();
// TODO: 入力値を使用して SmartTV オブジェクトを作成する
// TODO: 同じ TV オブジェクトを3つの異なる変数型に格納する:
// 1. SmartTV 型(具象クラス)
// 2. IControllable 型(インターフェース参照)
// 3. INetworkConnected 型(インターフェース参照)
// TODO: 要求された形式で出力を表示する:
// SmartTV 経由:
// - TurnOn() と Connect(network) を呼び出す
// IControllable 経由:
// - TurnOff() を呼び出す
// INetworkConnected 経由:
// - Connect(network) を呼び出す
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
5ポリモーフィズムとインターフェース
コンパイル時 vs 実行時ポリモーフィズムインターフェース vs 抽象クラス複数のインターフェース明示的なインターフェースアップキャストとダウンキャストまとめ - 図形計算機