C#と.netでは、派生クラスでインターフェイスメソッドを再実装できますが、派生クラスが可能性のある状況では、基本クラスで仮想メソッドを使用してインターフェイスを実装し、派生クラスでそのメソッドをオーバーライドする方がよい場合がよくあります。基本クラスの実装を完全に置き換えるのではなく、拡張したい。vb.netなどの一部の言語では、クラスが実装されているインターフェイスメンバーと同じ名前と署名を持つパブリックメンバーを公開しているかどうかに関係なく、これを直接実行できます。C#のような他の言語では、インターフェイスを実装するパブリックメソッドを非封印および仮想としてマークできます(派生クラスがそれをオーバーライドし、そのオーバーライド呼び出しをbase.Member(params)
行うことができますが、明示的なインターフェイス実装はできません。そのような言語では、できる最善の方法は何かです。お気に入り:
クラスMyClass:MyInterface
{{
void MyInterface.DoSomething(int param)
{{
doSomething(param);
}
保護された仮想voiddoSomething(int param)
{{
..。
}
}
クラスMyClass2:MyClass
{{
保護されたオーバーライドvoiddoSomething(int param)
{{
..。
base.doSomething(param);
..。
}
}
場合によっては、インターフェイス実装に仮想呼び出しをラップさせると、基本クラスがオーバーライドされた関数の前または後に特定のことが確実に発生するようになるため、有利な場合があります。たとえば、Disposeの非仮想インターフェイス実装は、仮想Disposeメソッドをラップできます。
int DisposedFlag; //System.BooleanはInterlocked.Exchangeでは機能しません
void IDisposable.Dispose()
{{
if(Threading.Interlocked.CompareExchange(DisposedFlag、1、0)== 0)
{{
Dispose(true);
DisposedFlag = 2;
Threading.Thread.MemoryBarrier();
GC.SuppressFinalize(this);
}
}
public bool Disposed {get {return(DisposedFlag!= 0);}}
public bool FullyDisposed {get {return(DisposedFlag> 1);}}
これにより、(Microsoftのデフォルトのラッパーとは異なり)Dispose
複数のスレッドが同時に呼び出そうとしても、一度だけ呼び出されるようになります。さらに、それはDisposed
プロパティを利用可能にします。Microsoftのラッパーを使用すると、フラグが必要なすべての派生クラスはDisposed
、独自のラッパーを定義する必要があります。基本クラスのDisposed
フラグが保護または公開されている場合でも、派生クラスが既にクリーンアップを開始するまで設定されないため、安全に使用することはできません。ラッパー内に設定DisposingFlag
すると、その問題を回避できます。