0

次のようなクラスがあるとしましょう。

public abstract class Foo
{
    public void Access(Foo foo)
    {
        /*
        if (foo is same type as implemented)
            AccessIfSameImplementation(foo);
        else
            AccessIfDifferentImplementation(foo);
        */
    }

    protected abstract void AccessIfSameImplementation(Foo foo);

    private void AccessIfDifferentImplementation(Foo foo)
    {
         //do stuff with the different implementations
    }
}

したがって、メソッドAccessはそれ自体の型を取り、定義により、継承している限り、それが何であるかをあまり気にしない実装になりFooます...しかし、このメソッドに、渡されたオブジェクトがその実装と同じ型。

そのようです:

public class Bar : Foo
{
    protected override void AccessIfSameImplementation(Foo foo)
    {
        // TODO: How do I force foo to always be a Bar
        // do specific Bar stuff
    }
}

現在、渡されたものが現在のものと同じNameかどうかを示すフィールドがあります。さらに、ジェネリックを使用することも考えましたが、それがこの問題に対する正しいアプローチだとは思いません。foo.NameName

編集:

私が使用している実際の構造について少し背景を説明します。

上記Fooで定義されたクラスは、一連のオブジェクトを作成するファクトリを表しています。List<X> objsこれらのオブジェクトは、実装されたFooオブジェクトのプロパティによって生成されます。現在、これらのファクトリを比較する別のクラスがありますが、ファクトリがすべて生成されることで肥大化することは望んでいません。したがって、ファクトリを肥大化させる代わりに、実装が同じかどうかをチェックするだけです。実装が同じである場合は、抽象比較子によって定義されたプロパティを比較し、そうでない場合は吹き飛ばします。後で時間があれば追加します。

もっといいタイトルがあれば、おすすめを教えてください。

4

3 に答える 3

1

あなたの意図がよくわかりませんが、子クラスの抽象メソッドの署名を変更することはできません。不適切な foo を取得した場合は、引数チェックを実行して例外をスローすることが考えられます。

public abstract class Foo
{
    public void Access(Foo foo)
    {
        if (foo.GetType() == GetType())
        {
            AccessIfSameImplementation(foo);
        }
        else
        {
            AccessIfDifferentImplementation(foo);
        }
    }

    protected abstract void AccessIfSameImplementation(Foo foo);

    private void AccessIfDifferentImplementation(Foo foo)
    {
        //do stuff with the different implementations
    }
}
public class Bar : Foo
{
    public string Baz { get; set; }

    protected override void AccessIfSameImplementation(Foo foo)
    {
        var bar = foo as Bar;

        if (bar == null)
        {
            throw new ArgumentException("Argument foo is not of type Bar");
        }

        //Do Bar stuff below
        bar.Baz = "Yay!";
    }
}
于 2013-04-25T01:07:30.923 に答える
1

複雑にしないでおく。抽象クラスを抽象に保ちますが、メソッドに不可知論Access的なデフォルトの実装を与えます。Foo子クラスのままにして、その子クラスのメンバーを使用するカスタム実装を提供します。子クラスが基本クラスに実装されているデフォルトのロジックにフォールバックすることをオプションにすることもできます。

public abstract class Foo
{
    public virtual void Access(Foo foo)
    {
        // perform the default implementation here, but mark as virtual to enable a child class to override it.
    }
}

public class Bar : Foo
{
    public override void Access(Foo foo)
    {
        var bar = foo as Bar;
        if (bar != null)
        {
            // If you get here, that means foo is a Bar.
            // Just use bar now and ignore foo.
        }
        else
        {
            // Fall back on the base classes implementation
            base.Access(foo);
        }
    }
}
于 2013-04-25T01:38:14.870 に答える