需要帮助理解实现接口的抽象类

时间:2009-07-09 23:58:08

标签: c# inheritance interface abstract-class

考虑以下示例。我有一个接口MyInterface,然后是两个抽象类MyAbstractClass1和MyAbstractClass2。 MyAbstractClass1实现MyInterface,但MyAbstractClass2不实现。

现在我有三个具体的课程。

  1. MyConcreteClass1派生自MyAbstractClass1,但未实现MyInterface。
  2. MyConcreteClass2派生自MyAbstractClass2,但确实实现了MyInterface。
  3. MyConcreteClass3派生自MyAbstractClass1,并实现MyInterface。
  4. ConcreteClass1是否也隐式实现MyInterface,因为它派生自MyAbstractClass1?假设MyAbstractClass1隐式实现了MyInteface的方法,那么不应该将ConcreteClass1强制转换为MyInterface来访问MyInteface方法吗?

    MyAbstractClass1可以隐式地将MyInterface的方法实现为抽象方法,但不能将MyInterface的方法显式实现为抽象方法。这是为什么?

    MyConcreteClass3是否过度,因为它正在实现一个已经由其基类实现的接口?即使您知道从MyAbstractClass1派生的所有类也应该实现MyInterface,您是否有理由想要这样做。

    这是一个类图

    alt text http://files.getdropbox.com/u/113068/abstractclassesandinterfaces.png

    以下是代码:

    //interface
    public interface MyInterface
    {
        void MyMethodA();
        void MyMethodB();
        void MyMethodC();
    
    }
    
    //abstract classes
    public abstract class MyAbstractClass1 : MyInterface
    {
        public void MyMethodA()
        {
        }
    
    
        void MyInterface.MyMethodB()
        {
    
        }
    
        //Error: "the modifier abstract is not valid for this item"
        //abstract void MyInterface.MyMethodC();
    
        //This works
        public abstract void MyMethodC();
    
        public abstract void MyMethodZ();
    
    }
    
    
    public abstract class MyAbstractClass2
    {
        public void MyMethodX()
        {
        }
    
        public abstract void MyMethodY();
    
    }
    
    //Concrete classes
    //ConcreteClass 1: Only Abstract class implements the interface
    public class ConcreteClass1 : MyAbstractClass1
    {
        public override void MyMethodC()
        {
        }
    
        public override void MyMethodZ()
        {
    
        }
    }
    
    //ConcreteClass 1: Only Concrete class implements the interface
    public class ConcreteClass2 : MyAbstractClass2, MyInterface
    {
        public override void MyMethodY()
        {
        }
    
        public void MyMethodA()
        {
    
        }
    
        public void MyMethodB()
        {
    
        }
    
        public void MyMethodC()
        {
    
        }
    
    }
    //ConcreteClass 1: Both concrete and abstract class implement the interface
    public class ConcreteClass3 : MyAbstractClass1, MyInterface
    {
        public override void MyMethodC()
        {
    
        }
    
        public override void MyMethodZ()
        {
    
        }
    }
    

3 个答案:

答案 0 :(得分:3)

  

ConcreteClass1是否也隐式实现MyInterface,因为它派生自MyAbstractClass1?

  

不应该将ConcreteClass1强制转换为MyInterface来访问MyInteface方法吗?

正确。 (myConcreteClass1 is MyInterface)将评估true

  

MyAbstractClass1可以隐式地将MyInterface的方法实现为抽象方法,但不能将MyInterface的方法显式实现为抽象方法。

明确的实现是区分重叠的成员签名。显式实现对于您正在实现它的类是私有的,因此派生类无法访问它(因此不能是抽象的)。您也不能强制从MyAbstractClass1派生的类显式实现MyInterface,因此无法确保抽象成员将被实现。

  

MyConcreteClass3是否过度,因为它正在实现一个已经由其基类实现的接口?即使您知道从MyAbstractClass1派生的所有类也应该实现MyInterface,您是否有理由想要这样做。

不一定,如果您需要显式实现接口的成员,以将其与MyConcreteClass3上的重叠成员区分开来。否则就没必要了。

答案 1 :(得分:1)

在这种情况下,所有三个类都实现了接口(直接或间接)。这是因为MyAbstractClass1实现了MyInterface,并且由于MyConcreteClass1派生自MyAbstractClass1,因此您可以将MyConcreteClass1视为MyInterface。 MyConcreteClass2可以使用派生自MyAbstractClass1的东西来处理,只要将其视为MyInterface即可。 ConcreteClass3中MyInterface的派生有点多余,因为MyAbstractClass1已经实现了MyInterface。

有了所有这些信息,我会说是的,在MyConcreteClass3上实现MyInterface是多余的,因为它派生自已实现MyInterface的MyAbstractClass1。 我认为你不能有一个接口方法的抽象实现的原因是它本身不提供代码,你不能保证它将在子类中被覆盖。请改用Virtual。

答案 2 :(得分:1)

这不是多余的。考虑这个类设置来简化......

public interface I
{
    void A();
}

public abstract class B : I
{
    public void A( )
    {
        Console.WriteLine("Base");
    }
}

public class D : B
{
    public void A()
    {
        Console.WriteLine("Hide");
    }
}

public class U
{
    public void M(I i)
    {
        Console.WriteLine("M!");
    }
}

执行此操作......

var d = new D();
var i = (I)d;
var u = new U();

i.A();
d.A();
u.M(d);
u.M(i);

你会得到......

Base
Hide
M!
M!

如果从派生类中添加界面...

public class D : B, I
{
  public void A()
  {
    Console.WriteLine("Hide");
  }
}

你会得到......

Hide
Hide
M!
M!

因此,当你获得派生类的Iness时,它会影响你获得的接口方法的实现。