「C Sharpの基礎 - インターフェイス」の版間の差分

ナビゲーションに移動 検索に移動
701行目: 701行目:
     // baseキーワードを使用することで、明示的にIB.Mメソッドを呼ぶことができる
     // baseキーワードを使用することで、明示的にIB.Mメソッドを呼ぶことができる
     public void M() => base(IB).M();
     public void M() => base(IB).M();
}
</syntaxhighlight>
<br>
==== 再抽象化 ====
標準実装を持つメンバを、再び、派生インターフェイス側で抽象メンバに戻すこともできる。<br>
明示的実装のような記述に、<code>abstract</code>修飾を付加する。<br>
<br>
以下の例では、Mメソッドが抽象メンバであるため、インターフェイスBを実装するクラスにはMメソッドの実装が必須となる。<br>
<u>この機能を、再抽象化(re-abstraction)と呼ぶ。</u><br>
<syntaxhighlight lang="c#">
using System;
interface A
{
    void M() => Console.WriteLine("default implementation");
}
interface B : A
{
    // 実装を持っているメソッドをabstractに変更する
    abstract void A.M();
}
// Mメソッドの実装が必須となるため、コンパイルエラーが起きる
class C : B
{
}
</syntaxhighlight>
<br>
==== その他の制限 ====
既存(C# 7.3以前)の破壊的変更が起きないようにするためであるが、その他、いくつか制限が存在する。<br>
派生クラスと派生インターフェイスで挙動が変わることもあるため、注意が必要である。<br>
<br>
まず、派生インターフェイスでは、オーバーライドは常に明示的実装が必要である。<br>
<syntaxhighlight lang="c#">
interface I
{
    void M() { }
}
interface IDerived : I
{
    // オーバーライドには明示的実装が必須
    void I.M()
    { }
    // 単にMメソッドを記述すると、別メソッドとなる
    // "別メソッドで基底のMメソッドを隠蔽する場合は、newを付加する"ように警告が出力される
    void M()
    { }
}
class C : I
{
    // クラスの場合はそのような制限は無く、publicの同名のメソッドを記述すればI.Mとして使用できる
    public void M()
    { }
}
</syntaxhighlight>
<br>
派生インターフェイスから基底インターフェイスのメンバを呼び出す場合は、クラスと同様である。<br>
一方、派生クラスからインターフェイスのメンバを呼び出す場合、標準実装のみ(オーバーライドしない)の時は、<br>
メンバを直接呼ぶことができない。<br>
<br>
また、protected修飾子のものを呼ぶこともできない。<br>
<syntaxhighlight lang="c#">
interface I
{
    void Abstract();
    void Default()
    { }
    protected void Protected()
    { }
}
interface IDerived : I
{
    void M()
    {
      // 派生クラスから基底クラスの呼び出しと同様
      // public, protected, 標準実装の有無も関係なく呼ぶことができる
      Abstract();
      Default();
      Protected();
    }
}
class C : I
{
    // 標準実装が無いものは実装が必須
    public void Abstract()
    { }
    public void M()
    {
      // 自身も実装を持つため呼ぶことができる。
      Abstract();
      // コンパイルエラー
      // インターフェイスの標準実装は直接呼ぶことができない
      Default();
      // インターフェイスの標準実装を呼ぶ場合は、キャストが必要となる
      ((I)this).Default();
      // protectedを付加したものは呼ぶことができない(コンパイルエラー)
      ((I)this).Protected();
    }
  }
  }
  </syntaxhighlight>
  </syntaxhighlight>

案内メニュー