3

今日、仮想として宣言されていないインターフェイスメソッドの実装をオーバーライドしようとして問題が発生しました。

この場合、インターフェイスまたは基本実装を変更できず、別のことを試す必要がありますが、仮想メソッドを使用してクラスにインターフェイスを実装させる方法があるかどうか疑問に思いました。

例:

interface IBuilder<T>
{
    // Already implicitly virtual
    /*virtual*/ T Build();
}

// This is a class written by someone else
class SimpleBuilder: IBuilder<SomeObject>
{
    // I would like to force this to be virtual
    public SomeObject Build() { return new SomeObject(); }
}

// This is the class I am writing.
class CustomBuilder: SimpleBuilder
{
    public /*override*/ SomeObject Build()
    {
        var obj = base.Build();
        obj.ModifyInSomeWay();
        return obj;
    }
}

編集: MEFで使用することを目的としているため、MEFが正しいタイプを解決するためにCustomBuilder派生しています。SimpleBuilderインターフェイスを明示的に実装しようとしましたが、まったく派生しSimpleBuilderていませんが、MEFは正しいタイプを選択しません。

問題のインターフェースと基本クラスは別の開発者によって作成された共有モジュールにあるため、とにかく基本クラスを変更する必要があるようです。

4

5 に答える 5

3

いいえ、あなたの例では暗黙的にインターフェースを実装しています。クラスがサブクラス化され、メソッドがオーバーライドされることを意図している場合、メソッドが仮想としてマークされていることを確認するのは開発者次第です。

インターフェイス メソッドの実装をコードで強制的にオーバーライド可能にする方法はありません。これを保証できるのは開発チーム内の規則だけです (たとえば、すべてのインターフェイスを明示的に実装する必要がある、すべてのインターフェイス実装を仮想としてマークする必要があるなど)。

この特定の例では、抽象クラスを階層に挿入できます。

abstract class VirtualBuilder<T> : IBuilder<T>
{
  abstract T Build();
}

ただし、これは一般的なケースには適していません。インターフェイスの利点を失い、すべての具体的なクラスに 1 つのインターフェイスのみを実装するよう強制するからです。

于 2012-07-03T10:44:36.487 に答える
2

直接ではありません。

独自の基本クラスを提供し、ユーザーがそれから派生することを要求することで、それを「強制」できます。

abstract class BuilderBase<T> : IBuilder<T>
{
    public abstract T Build();
}

しかし、これには深刻な問題もあります。

  1. 誰もがインターフェイスを直接実装するのをすぐに止めるわけではありません (ただし、たとえば、着信パラメーターをBuilderBase<T>単に ではなく にすることを要求したり、別のアセンブリでそれを作成して非表示にしたりすることIBuilder<T>もできます)。IBuilder<T> internal
  2. インターフェイスの実装者に、単一の基本クラスの選択を放棄するように強制します。
于 2012-07-03T10:47:37.140 に答える
1

強制的に仮想にすることはできませんが、 new キーワードを使用できます。それはMethod Hidingと呼ばれます。

// This is the class I am writing. 
class CustomBuilder: SimpleBuilder, IBuilder<T> 
{ 
    public new SomeObject Build() 
    { 
        var obj = base.Build(); 
        obj.ModifyInSomeWay(); 
        return obj; 
    } 
} 
于 2012-07-03T10:44:25.610 に答える
0

インターフェイス メソッドの実装方法を指定することはできません。

ただし、基本実装が仮想でなくても、サブクラスでインターフェイス メソッドを再実装するには 2 つの方法があります。

  • newメソッド修飾子を使用して基本実装を非表示にする、または
  • 次のような明示的なインターフェイスの実装:

    T IBuilder.Build() { var obj = Build(); obj.ModifyInSomeWay(); オブジェクトを返します。}

これらのアプローチのいずれかにより、クラスがインターフェイスを介してアクセスされた場合にのみメソッドが呼び出されますが、呼び出しで基本クラスの参照が使用されている場合は呼び出されません。

したがって、この基本クラスは継承による拡張の準備ができていないと言えます。

于 2012-07-03T10:47:51.737 に答える
0

インターフェイスはクラスがどのように見えるべきかを説明するだけで、実装自体については何も言わないため、これを行うことはできません。

言い換えれば、メソッドを定義するインターフェースを実装するクラスを使用する場合、Foo()実装に関係なく、そのクラスにはこのメソッドがあると確信できます。

できること:

public interface IBuilder<T>
{
    T Build();
}

public abstract class BaseBuilder<T> : IBuilder<T>
{
    public abstract T Build();
}

public class CustomBuilder : BaseBuilder<CustomBuilder>
{
    public override CustomBuilder Build()
    {
        throw new NotImplementedException();
    }
} 
于 2012-07-03T10:51:28.410 に答える