Нужна помощь в понимании абстрактных классов, которые реализуют интерфейс - PullRequest
3 голосов
/ 10 июля 2009

Рассмотрим следующий пример. У меня есть интерфейс MyInterface, а затем два абстрактных класса MyAbstractClass1 и MyAbstractClass2. MyAbstractClass1 реализует MyInterface, а MyAbstractClass2 - нет.

Теперь у меня есть три конкретных класса.

  1. MyConcreteClass1 является производным от MyAbstractClass1, но не реализует MyInterface.
  2. MyConcreteClass2 является производным от MyAbstractClass2, но реализует MyInterface.
  3. MyConcreteClass3 является производным от MyAbstractClass1 и реализует MyInterface.

Реализует ли ConcreteClass1 также неявно MyInterface, поскольку он является производным от MyAbstractClass1? Предполагая, что MyAbstractClass1 неявно реализует методы MyInteface, тогда не нужно приводить ConcreteClass1 к MyInterface для доступа к методам MyInteface, верно?

MyAbstractClass1 может неявно реализовывать метод MyInterface как абстрактный метод, но не может явно реализовывать метод MyInterface как абстрактный метод. Почему это?

Является ли MyConcreteClass3 чрезмерным, потому что он реализует интерфейс, который уже реализован его базовым классом? Будет ли причина, по которой вы захотите это сделать, даже если вы знали, что все классы, производные от MyAbstractClass1, также должны реализовывать MyInterface.

Вот диаграмма классов

альтернативный текст 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 ]

3 голосов
/ 10 июля 2009

Реализует ли ConcreteClass1 также неявно MyInterface, поскольку он является производным от MyAbstractClass1?

Да.

ConcreteClass1 не должен приводиться к MyInterface для доступа к методам MyInteface, верно?

Правильно. (myConcreteClass1 is MyInterface) будет оценивать true.

MyAbstractClass1 может неявно реализовывать метод MyInterface как абстрактный метод, но не может явно реализовывать метод MyInterface как абстрактный метод.

Явная реализация заключается в том, чтобы различать перекрывающиеся подписи членов. Явная реализация является закрытой для класса, в котором вы ее реализуете, поэтому она недоступна для производных классов (и поэтому не может быть абстрактной). Вы также не можете заставить классы, производные от MyAbstractClass1, явно реализовывать MyInterface, поэтому нет способа гарантировать, что абстрактный член когда-либо будет реализован.

Является ли MyConcreteClass3 чрезмерным, потому что он реализует интерфейс, который уже реализован его базовым классом? Будет ли причина, по которой вы захотите это сделать, даже если вы знали, что все классы, производные от MyAbstractClass1, также должны реализовывать MyInterface.

Не обязательно, если вам нужно явно реализовать элемент интерфейса, чтобы отличить его от перекрывающегося элемента в MyConcreteClass3. В противном случае это не нужно.

1 голос
/ 10 июля 2009

Это не избыточно. Рассмотрим настройку этого класса для упрощения ...

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 вашего производного класса.

1 голос
/ 10 июля 2009

В этом случае все три класса реализуют интерфейс (прямо или косвенно). Это связано с тем, что MyAbstractClass1 реализует MyInterface, и поскольку MyConcreteClass1 является производным от MyAbstractClass1, из этого также следует, что MyConcreteClass1 можно рассматривать как MyInterface. MyConcreteClass2 может обрабатываться чем-то, что происходит от MyAbstractClass1, если вы рассматриваете его как MyInterface. вывод из MyInterface в ConcreteClass3 немного избыточен, поскольку MyAbstractClass1 уже реализует MyInterface.

Со всей этой информацией, я бы сказал, что да, избыточно реализовывать MyInterface на MyConcreteClass3, поскольку оно происходит от MyAbstractClass1, который уже реализует MyInterface. Я думаю, что причина того, что у вас не может быть абстрактной реализации метода интерфейса, состоит в том, что он не предоставляет сам код, и вы не можете гарантировать, что он будет переопределен в subcalsses. Вместо этого используйте Virtual.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...