Добавление новых функций к интерфейсу

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

Я полагаю, что у меня есть несколько опций:

Интерфейс Simplified Original:

public interface IServerComponent
{
    bool Add(int a, int b);
}

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

public interface IServerComponent
{
    bool Add(int a, int b);
    bool Add(int a, int b, int c);
}

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

public interface IServerComponent2 : IServerComponent
{
    bool Add(int a, int b, int c);
}

То, какова лучшая практика, является этой ситуацией? Действительно ли там какие-либо другие опции доступны?

Спасибо

9
задан fletcher 15 July 2010 в 13:42
поделиться

6 ответов

Если новые методы могут быть выражены в терминах старых методов, вы можете использовать методы расширения:

// Original interface
public interface IServerComponent 
{ 
  bool Add(int a, int b, int c); 
} 

// New overload
public static class MyServerMethods
{
  public static bool Add(this IServerComponent component, int a, int b)
  {
    return component.Add(a, b, 0);
  }
}

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

12
ответ дан 4 December 2019 в 12:16
поделиться

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

Например

public interface IAddableThings
{
  int a;
  int b;
}

public interface IOtherAddableThings : IAddableThings
{
  int a;
  int b;
}

public interface IServerComponent
{
    bool Add(IAddableThings things);
}

Если это действительно Add, то я думаю, что это имеет гораздо больше смысла, но если это действительно больше похоже на Calculate(), то вы захотите перенести некоторые или все операции этого метода в объекты IAddableThings.

public interface IAddableThings
{
  int a;
  int b;
  bool CalculateMe();
}
1
ответ дан 4 December 2019 в 12:16
поделиться

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

0
ответ дан 4 December 2019 в 12:16
поделиться

Я думаю, что поддерживать один интерфейс проще, но второй подход с двумя интерфейсами лучше, потому что не каждый класс должен реализовывать bool Add(int a, int b, int c);

0
ответ дан 4 December 2019 в 12:16
поделиться

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

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

0
ответ дан 4 December 2019 в 12:16
поделиться

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

В противном случае создайте интерфейс IServerComponent2, расширяющий IServerComponent. IIRC, это то, что рекомендуют Руководящие принципы разработки инфраструктуры. Пример этого можно найти в .NET Framework в виде класса X509Certificate2 .

Однако, если новые элементы могут быть реализованы в терминах исходных элементов, вы также можете использовать методы расширения :

public interface IServerComponent
{
    bool Add(int a, int b);
}

public static class ServerComponentExtensions
{
    public static bool Add(this IServerComponent isc, int a, int b, int c)
    {
        return isc.Add(a, b) && isc.Add(b, c) && isc.Add(c, a);
    }
}
4
ответ дан 4 December 2019 в 12:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: