Почему базовый класс в C # позволяет реализовать интерфейсный контракт, не наследуя его? - PullRequest
17 голосов
/ 31 мая 2010

Я наткнулся на эту "особенность" C # - базовый класс, который реализует методы интерфейса, не должен наследовать от него .

Пример:

public interface IContract
{
    void Func();
}

// Note that Base does **not** derive from IContract
public abstract class Base
{
    public void Func()
    {
        Console.WriteLine("Base.Func");
    }
}

// Note that Derived does *not* provide implementation for IContract
public class Derived : Base, IContract
{
}

Что происходит, когда Derived волшебным образом подбирает открытый метод Base.Func и решает, что он реализует IContract.Func.

В чем причина этой магии?

ИМХО: эта функция «квазиреализации» очень неинтуитивна и значительно затрудняет проверку кода.Что ты думаешь?

Ответы [ 2 ]

32 голосов
/ 31 мая 2010

Причина в том, что ваш комментарий просто неверен:

// Обратите внимание, что Derived не обеспечивает реализацию для IContract

Конечно, это так. Следуйте логике до конца.

  • Производное требуется для предоставления открытого члена, соответствующего каждому члену IContract.
  • Все наследуемые члены базового класса также являются членами производного класса; это определение наследования.
  • Поэтому Derived предоставляет реализацию для IContract; его унаследованный член является членом, который удовлетворяет требованию
  • Следовательно, без ошибок.

эта функция очень неинтуитивна и значительно затрудняет проверку кода. Что ты думаешь?

Я думаю, вам не следует использовать эту функцию, если она вам не нравится. Если вам кажется странным и странным читать код, использующий эту функцию, попросите коллег, использующих эту функцию, прекратить это делать.

Чем эта функция отличается от любой другой функции, где метод из базового класса используется из производного класса? Существует несколько различных способов использования или упоминания метода из базового класса в производном классе - вызовы методов, переопределения, преобразования групп методов и т. Д.

Кроме того, это относительно простой и понятный случай. Если вы действительно хотите пожаловаться на запутанную семантику интерфейса в C #, я бы потратил свое время на жалобы на семантику переопределения интерфейса . Это тот, который действительно, кажется, печет лапшу людей. Мне всегда нужно искать это в спецификации, чтобы убедиться, что я правильно понимаю семантику.

12 голосов
/ 31 мая 2010

Почему вы думаете, что это странно и неестественно? Каждый открытый член базового класса также является открытым членом производного класса. Так что здесь нет противоречия. В любом случае, вы можете явно реализовать интерфейс, если хотите.

...