Подтвердить что ты не робот

Если один интерфейс наследует другой интерфейс

Я не могу найти ответ на этот вопрос и просто хочу убедиться, что он соответствует стандарту кодирования. У меня есть интерфейс А, который используется многими разными классами и не требует изменения интерфейса А. Я столкнулся с новым требованием, которое потребует перечисления, которое потребуется многим из классов, реализующих интерфейс A, но не всем классам требуется это перечисление. Я не хочу, чтобы классы, которые не нуждаются в этом новом перечислении для реализации этой новой функции. Поэтому я создал интерфейс B, содержащий новое перечисление, которое мне нужно было добавить. Затем я сделал интерфейс B Inherit Interface A, и это мое беспокойство. Является ли в порядке для одного интерфейса для наследования другого интерфейса? Чтобы продолжить мои изменения, я изменил классы, которые нуждались в новом перечислении для реализации интерфейса B вместо интерфейса A, поскольку он был унаследован интерфейсом B. Я думал об использовании обоих интерфейсов в своих классах, которые им были нужны, но я использую Интерфейс по всему коду и хотел бы просто использовать один интерфейс для просмотра классов, а не двух.

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

Спасибо!

4b9b3361

Ответ 1

Наследование на интерфейсе - отличный инструмент, хотя вы должны использовать его только тогда, когда интерфейс B по-настоящему подменяется для интерфейса A, а не просто для объединения свободно связанных действий.

Трудно сказать, подходит ли это для вашего конкретного случая, но в принципе нет ничего плохого в практике. Вы видите это в первоклассных API-интерфейсах все время. Чтобы выбрать только один общий пример из платформы .NET:

public interface ICollection<T> : IEnumerable<T>, IEnumerable

Ответ 2

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

Давайте рассмотрим пример:

public interface IScanner
{
    void Scan();
}

public interface IPrinter
{
    void Print();
}

Принтеры и сканеры часто являются отдельными объектами, каждый со своей собственной функциональностью, однако эти два устройства часто соединяются в одном устройстве;

public interface IPhotocopier : IScanner, IPrinter
{
    void Copy();
}

Имеет смысл, что IPhotocopier должен наследовать от IScanner и IPrinter, поскольку теперь это позволяет использовать копировальный аппарат как сканер или принтер (который он содержит) в дополнение к его первичному ролику в качестве копира.

Теперь рассмотрим еще один интерфейс:

public interface IBlender
{
    void Blend();
}

Не имеет смысла позволять IBlender наследоваться с помощью любого из предыдущих интерфейсов (что бы вы назвали их? IBlendingScanner?).

Если вы не можете дать вашему новому интерфейсу разумное имя, это может указывать на то, что вы не можете использовать наследование в этом экземпляре.

Неплохая идея наследовать некоторые интерфейсы, такие как IDisposable, поскольку это заставляет все реализации вашего нового интерфейса реализовать шаблон размещения, даже если у них нет доступных ресурсов.

Ответ 3

Конечно, возможно иметь дерево наследования интерфейсов и даже "множественное наследование" с интерфейсами. Правильно ли это делать или нет, зависит от рассматриваемых интерфейсов. Если на самом деле интерфейс B является расширением или уточнением интерфейса A, то наследование имеет смысл, но если новое перечисление в значительной степени не связано с понятием, выраженным интерфейсом A, я бы сделал их двумя отдельными интерфейсами и имел классы которые должны реализовать оба интерфейса.

Ответ 4

С технической точки зрения, интерфейсы не наследуют друг от друга. Что действительно происходит при создании IFoo, который наследуется от IBar, вы говорите, что любой класс, реализующий IFoo, должен также реализовать IBar.

interface IBar
{
    void DoBar();
}

interface IFoo : IBar
{
    void DoFoo();
}

В этом примере интерфейс IFoo не имеет метода DoBar(). В большинстве случаев это различие не имеет значения, но оно может укусить вас при использовании отражения на интерфейсе, а не на классе.

Ответ 5

IMO это точно правильный подход, я не вижу никаких проблем с ним.

Ответ 6

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

IMySqlDatabase : IDatabase
MySqlDatabase : IMySqlDatabase

IMsSqlDatabase : IDatabase
MsSqlDatabase : IMsSqlDatabase

MySqlDatabase - это база данных IMySql, а IMySqlDatabase IS - база данных.

Теперь, если вам нужно внести изменения в свой интерфейс базы данных, внуки (классы базы данных для конкретных классов) могут воспользоваться преимуществами, но вам не придется расширять MySQL и MsSQL (или, возможно, даже больше интерфейсов СУБД). В то же время у вашего среднего человека (IMsSqlDatabase) вы все еще можете иметь интерфейсные функции, которые не поддерживали бы MySQL или Oracle DB.