12,788
回編集
(→多重継承) |
|||
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> |