奇怪的继承修改

时间:2011-10-27 19:52:37

标签: c# .net oop inheritance abstraction

我是.NET开发人员,对OOP非常了解。 然而,最近我注意到一个有趣的事实。

System.Data.SqlClient.SqlCommand源自 System.Data.Common.DbCommand。后者实现了System.IDbCommandSystem.IDbCommand公开Connection的实例IDbConnection。 在DbCommand但是此属性返回DbConnection类型。最后,SqlCommand中的同一属性属于SqlConnection

类型

我尝试执行相同操作但是它给出了编译时错误。在上面的示例中如何实现这一点,如何重新创建相同的模式?

我的代码(不编译):

public interface IFoo { }
public interface IBar 
{
   IFoo TheFoo();
}

public abstract class AbsFoo : IFoo { }
public abstract class AbsBar : IBar 
{
    public abstract AbsFoo TheFoo();
}

public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { }

3 个答案:

答案 0 :(得分:4)

Explicit interface implementation是这里游戏的名称。试试这个:

public abstract class AbsBar : IBar {
    IFoo IFoo.TheFoo() { return this.TheFoo(); }
    public abstract AbsFoo TheFoo();
}

这是implicit vs. explicit implementation的好指南。

答案 1 :(得分:2)

我不得不说,我认为理查德有点难以做到 - 他的回答与 Jason 一样好,因为他们都只回答了一半这个问题。 将它们放在一起就可以得到完整的答案。

使用IDbCommandDbCommand& SqlCommand必须在IDbCommand中明确实施DbCommand Jason的回答)以及SqlCommand中的公共方法阴影( Richard's}答案)。

我会给出完整的“Foo / Bar”示例。

从这些界面开始:

public interface IFoo
{
    IBar GetBar();
}

public interface IBar { }

下一个Foo必须提供IFoo的明确实施,才能从Bar方法返回IBar,而不是GetBar

public abstract class Foo : IFoo
{
    IBar IFoo.GetBar()
    {
        return this.GetBar();
    }

    public Bar GetBar()
    {
        return this.GetBarInner();
    }

    protected abstract Bar GetBarInner();
}

public abstract class Bar : IBar { }

最后,SomeFoo类必须隐藏GetBar以便能够返回SomeFoo个实例:

public class SomeFoo : Foo
{
    public new SomeBar GetBar()
    {
        return new SomeBar();
    }

    protected override Bar GetBarInner()
    {
        return this.GetBar();
    }
}

public class SomeBar : Bar { }

我认为理查德唯一的信息就是我将new关键字添加到阴影方法中,以消除编译错误。

答案 2 :(得分:1)

DbCommand和SqlCommand中的连接都只是公共方法。会有一个编译器警告,但它是允许的。您的代码应该更像是像SqlCommand / DbCommand一样工作:

    public interface IFoo { }
public abstract class AbsBaseBar
{
    public IFoo TheFoo() { throw new NotImplementedException(); }
}
public class AbsFoo : IFoo { }
public class AbsBar : AbsBaseBar
{
    public AbsFoo TheFoo() { throw new NotImplementedException(); }
}

public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { }