インターフェイスを利用した多重継承 - C#

C#でのインターフェイスを利用した多重継承のコードを紹介します。

概要

C#でクラスからの多重継承のクラスはできませんが、インターフェイスを利用すると多重継承のクラスを作成できます。
この記事では、複数のインターフェイスを継承した田淳景勝のクラスのコードを紹介します。

プログラム例

UI

下図のフォームを作成します。
ボタンとMultilineプロパティをtrueに設定した、複数行のテキストボックスを配置します。

コード

下記のコードを記述します。
MyInterface1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultipleInheritance
{
  internal interface MyInterface1
  {
    int set(int id, string value);
    int delete(int id);
    int swap(int pos1, int pos2);
  }
}
MyInterface2.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultipleInheritance
{
  internal interface MyInterface2
  {
    IEnumerable<string> GetItem();
  }
}
MyClass1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultipleInheritance
{
  public class MyClass1 : MyInterface1, MyInterface2
  {
    string[] Item;

    public MyClass1()
    {
      Item = new string[3];
    }

    public int set(int id, string value)
    {
      if (Item.Length < id)
      {
        return -1;
      }
      else
      {
        Item[id] = value;
        return 0;
      }
    }

    public int delete(int id)
    {
      if (Item.Length < id)
      {
        return -1;
      }
      else
      {
        Item[id] = "";
        return 0;
      }
    }

    public int swap(int pos1, int pos2)
    {
      string temp = Item[pos1];
      Item[pos1] = Item[pos2];
      Item[pos2] = temp;

      return 0;
    }

    public IEnumerable<string> GetItem()
    {
      List<string> ListItem = new List<string>();

      for (int i = 0; i < Item.Length; i++) {
        ListItem.Add(Item[i]);
      }

      return ListItem;
    }
  }
}
フォームのコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MultipleInheritance
{
  public partial class FormSimpleMultipleInheritance : Form
  {
    public FormSimpleMultipleInheritance()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      MyClass1 mc1 = new MyClass1();
      mc1.set(0, "ぺんぎんクッキー");
      mc1.set(1, "らくだキャラメル");
      mc1.set(2, "かるがもサブレ");

      mc1.swap(0, 2);
      foreach (string item in mc1.GetItem())
      {
        textBox1.Text += item + "\r\n";
      }

    }
  }
}

解説

MyInterface1.cs

インターフェイスを定義しています。MyInterface1 には set delete swap の3つの抽象メソッドを定義しています。
namespace MultipleInheritance
{
  internal interface MyInterface1
  {
    int set(int id, string value);
    int delete(int id);
    int swap(int pos1, int pos2);
  }
}

MyInterface2.cs

2つの目のインターフェイスです。こちらのインターフェース MyInterface2 には GetItem 抽象メソッドを定義しています。
namespace MultipleInheritance
{
  internal interface MyInterface2
  {
    IEnumerable<string> GetItem();
  }
}

MyClass1.cs

多重継承のクラスを定義してメソッドを実装しています。
多重継承する場合は、継承元にインターフェイスを指定し、継承するインターフェイスを複数 , で区切って記述します。
下記コードでは、MyClass1 は MyInterface1 と MyInterface2 を継承したクラスになります。
  public class MyClass1 : MyInterface1, MyInterface2
  {
    /* 中略 */
  }

MyClassはMyInterface1 と MyInterface2 を継承しているため、両方のインターフェイスの抽象メソッドを実装している必要があります。
クラスに、set delete swap GetItem のメソッドを実装します。
  public class MyClass1 : MyInterface1, MyInterface2
  {
    public int set(int id, string value)
    {
      /* 中略 */   
    }

    public int delete(int id)
    {
      /* 中略 */
    }

    public int swap(int pos1, int pos2)
    {
      /* 中略 */
    }

    public IEnumerable<string> GetItem()
    {
      /* 中略 */
    }
  }

今回の実装では、内部の情報格納に配列を利用しています。配列の長さは3としています。
    string[] Item;

    public MyClass1()
    {
      Item = new string[3];
    }

setメソッドは値を指定した配列の位置に格納します。
    public int set(int id, string value)
    {
      if (Item.Length < id)
      {
        return -1;
      }
      else
      {
        Item[id] = value;
        return 0;
      }
    }

deleteメソッドは指定した配列の位置の値をから文字列にします。
    public int delete(int id)
    {
      if (Item.Length < id)
      {
        return -1;
      }
      else
      {
        Item[id] = "";
        return 0;
      }
    }

swapメソッドは2つの配列の値を入れ替える処理を実装しています。
    public int swap(int pos1, int pos2)
    {
      string temp = Item[pos1];
      Item[pos1] = Item[pos2];
      Item[pos2] = temp;

      return 0;
    }

GetItemメソッドは配列の3つの値をListで返す処理を実装しています。
    public IEnumerable<string> GetItem()
    {
      List<string> ListItem = new List<string>();

      for (int i = 0; i < Item.Length; i++) {
        ListItem.Add(Item[i]);
      }

      return ListItem;
    }

フォーム

フォームではボタンのクリックにより下記のコードを実行します。 MyClass1を作成し、set メソッドで3つの値を設定します。 次に swap メソッドを呼び出し、0と2の要素を入れ替えます。 最後に GetItem メソッドを呼び出し値をテキストボックスに表示します。 0番目と2番目を入れ替えているため、次の順番で結果が表示されれば正しい動作です。
  • かるがもサブレ
  • らくだキャラメル
  • ぺんぎんクッキー
    private void button1_Click(object sender, EventArgs e)
    {
      MyClass1 mc1 = new MyClass1();
      mc1.set(0, "ぺんぎんクッキー");
      mc1.set(1, "らくだキャラメル");
      mc1.set(2, "かるがもサブレ");

      mc1.swap(0, 2);
      foreach (string item in mc1.GetItem())
      {
        textBox1.Text += item + "\r\n";
      }
    }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。カルガモサブレ らくだキャラメル ぺんぎんクッキー の順番でテキストボックスに値が表示されます。 期待した通りの動作結果になっています。
また、MyClass1 にMyInterface1とMyInterface2 の継承とメソッドの実装ができていることも確認できます。


C#でインターフェイスを複数継承した多重継承のクラスを作成できました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2022-01-27
iPentec all rights reserverd.