如何指定子类使用它们的类型?

时间:2013-04-25 00:48:33

标签: c# generics object-oriented-analysis

假设我有一个这样的课程:

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.Name是否与当前的Name相同除此之外我还考虑过使用泛型但是再次认为不是正确处理这个问题。

修改

我正在使用的实际结构的一些背景知识。

上面定义的Foo类代表了一个工厂,它创建了一组对象List<X> objs这些对象是由实现的Foo对象的属性生成的。现在我有一些其他的比较这些工厂的课程,但我不希望工厂通过生成它们而变得臃​​肿。因此,我只是检查它们是否具有相同的实现,而不是*膨胀工厂,如果是这样,则比较抽象比较器定义的属性,否则*井喷。我有一段时间后会添加更多。

如果有人有更好的头衔,请推荐一个。

3 个答案:

答案 0 :(得分:2)

Aright所以我猜我完全不能完全考虑事情。所有需要做的是直接在公共方法Access

中进行类型比较
public void Access(Foo foo)
{
    if (GetType() == foo.GetType) //Duh...
    {
         AccessIfSameImplementation(foo);
    }
    else
    {
         AccessIfDifferentImplementation(foo);
    }
}

答案 1 :(得分: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!";
    }
}

答案 2 :(得分: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);
        }
    }
}