Добавление новых функций в интерфейс - PullRequest
9 голосов
/ 15 июля 2010

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

Я полагаю, у меня есть несколько вариантов:

Упрощенная Оригинальный интерфейс:

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);
}

Какая лучшая практика в этой ситуации? Есть ли другие доступные варианты?

Спасибо

Ответы [ 6 ]

11 голосов
/ 15 июля 2010

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

// 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);
  }
}

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

4 голосов
/ 15 июля 2010

Если ваш интерфейс 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);
    }
}
1 голос
/ 15 июля 2010

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

Например

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();
}
0 голосов
/ 15 июля 2010

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

0 голосов
/ 15 июля 2010

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

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

0 голосов
/ 15 июля 2010

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

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