Каков наилучший способ показать реализацию унаследованного интерфейса в C #? - PullRequest
3 голосов
/ 26 января 2009

Имеются следующие интерфейсы:

interface IFoo
{
    void Foo();
}

interface IBar : IFoo
{
    void Bar();
}

как лучше всего указать, что данный класс реализует IBar?

Подход A:

class Implementation : IBar { ... }

Это кажется проще и чище, но это не означает, что Implementation реализует IFoo.

Подход B:

class Implementation : IBar, IFoo { ... }

Это кажется наиболее информативным, но действительно ли необходима дополнительная информация?

Ответы [ 7 ]

6 голосов
/ 26 января 2009

Лично я бы пошел с первым. С последним скажем, что вы находитесь в такой ситуации, когда у вас есть куча производных классов:

class DerivedA : Implementation, IBar, IFoo { ... }
class DerivedB : Implementation, IBar, IFoo { ... }
class DerivedC : Implementation, IBar, IFoo { ... }
class DerivedD : Implementation, IBar, IFoo { ... }

И тогда ваши требования к Implementation изменятся, так что теперь ему необходимо реализовать другой интерфейс, такой как IBaz (что он может делать, не затрагивая ни один из производных классов, если он обеспечивает неабстрактную реализацию ) тогда у вас есть два варианта:

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

  2. Идите и найдите все производные классы и все их производные классы и исправьте объявления на них. Это требует времени, несколько подвержено ошибкам, и его трудно полностью выполнить, и превращает изменение одного файла в многофайловую регистрацию.

Ни один из этих вариантов не является привлекательным, поэтому я бы выбрал вариант, который не поставит вас в ту или иную ситуацию. Просто объявите самый производный интерфейс.

6 голосов
/ 26 января 2009

Дополнительная информация не нужна компилятору, но может оказаться полезной для читателя вашего кода, так как читателю не нужно знать, что IBar расширяет IFoo. Примером этого в рамках может быть List<T>, который реализует <IList<T>, ICollection<T> и IEnumerable<T>, хотя IList<T>; расширяет как ICollection<T>, так и IEnumerable<T>.

РЕДАКТИРОВАТЬ : Я думаю, по крайней мере для меня, основная причина, по которой я бы перечислил оба, состоит в том, что вы обычно не думаете об интерфейсах, наследуемых друг от друга. Когда вы наследуете класс, вы ожидаете, что вы наследуете поведение, которое само по себе может быть унаследовано. Если вы заинтересованы, вы следуете за производными по иерархии классов. С интерфейсом это более необычно, что интерфейс будет производным, и, таким образом, вы будете иметь меньше шансов посмотреть и скорее пропустить соединение. Перечисление их обоих решает эту проблему без особой боли.

1 голос
/ 26 января 2009

Тот факт, что вы уже реализовали IFoo в IBar, означает, что вам даже не нужно указывать, что ваш конкретный класс реализации реализует IFoo; CLR может вывести это, и если вы используете Reflector в вашей сборке, вы увидите, что он указывает, что Implementation реализует и IFoo и IBar, даже если вы используете подход A.

Так что Подход А это.

1 голос
/ 26 января 2009

Я бы пошел с А. Вы увидите, какие методы вам нужно реализовать в самом классе, а инструменты навигации в IDE помогут вам с остальными.

B было бы невозможно поддерживать при проведении любого рефакторинга (например, что произойдет, если вы замените IBar или разделите его на 2?)

0 голосов
/ 26 января 2009

Я бы выбрал подход А просто потому, что перечисление интерфейса в списке производных для определения класса подразумевает, что вы предоставляете реализацию в этом классе. Если вы не собираетесь предоставлять альтернативную реализацию IFoo, я бы не включил ее в список, если вам не нужен простой «интерфейс маркера». Тем не менее, даже тогда во время выполнения оператор «is» (возвращающий true или false) или ключевое слово «as» (возвращающий объект или null) сообщит вам, можно ли привести объект к IFoo.

0 голосов
/ 26 января 2009

Помимо читабельности и различий в VB.NET (см. Комментарии Кэтлин Доллард), существует ситуация с привязкой данных, которая требует (B). Детали сорвались с ума (я буду редактировать, если кто-то не победит меня ...).

Я думаю, именно поэтому коллекции .NET Framework явно реализуют свои производные интерфейсы.

0 голосов
/ 26 января 2009

Я думаю, что подход A достаточно ясен, потому что (в любом случае в VS.NET) вы можете очень быстро определить, что IBar реализует IFoo.

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