Интерфейс, аннотация или просто виртуальные методы? - PullRequest
8 голосов
/ 29 сентября 2011

У меня есть несколько систем, давайте назовем их A, B, C, D, E, F, G, H, I, J.

Все они имеют сходные методы и свойства.Некоторые содержат точно такой же метод и свойства, некоторые могут немного отличаться, а некоторые могут сильно различаться.Прямо сейчас у меня много дублированного кода для каждой системы.Например, у меня есть метод с именем GetPropertyInformation(), который определен для каждой системы.Я пытаюсь выяснить, какой метод был бы лучшим подходом для уменьшения дублирующегося кода или, возможно, один из методов ниже не подходит:

Интерфейс

public Interface ISystem
{
    public void GetPropertyInformation();
    //Other methods to implement
}

public class A : ISystem
{
    public void GetPropertyInformation()
    {
       //Code here
    }
}

Аннотация

public abstract class System
{
    public virtual void GetPropertyInformation()
    {
        //Standard Code here
    }
}

public class B : System
{
   public override void GetPropertyInformation()
   {
      //B specific code here
    }
}

Виртуальные методы в классе Super Base

public class System
{
   public virtual void GetPropertyInformation()
    {
     //System Code
    }
}

public class C : System
{
  public override void GetPropertyInformation()
  {
      //C Code
  }
}

Один вопрос, хотя он может быть глупым,давайте предположим, что я пошел с абстрактным подходом и хотел переопределить GetPropertyInformation, но мне нужно было передать ему дополнительный параметр, это возможно, или мне нужно было бы создать другой метод в абстрактном классе?Например, GetPropertyInformation(x)

Ответы [ 6 ]

6 голосов
/ 29 сентября 2011

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

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

Если классы A, B, C, естественно, не принадлежат одному «семейству», используйте интерфейс.

И System не такое доброе имя.

И вы не можете изменить список параметров при переопределении.Возможно, параметры по умолчанию могут помочь, в противном случае вам просто нужно 2 перегрузки для GetPropertyInformation ().

3 голосов
/ 29 сентября 2011

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

public Interface ISystem
{
    public void GetPropertyInformation();
    //Other methods to implement
}

public abstract class System : ISystem
{
    public virtual void GetPropertyInformation()
    {
        //Standard Code here
    }
}

public class B : System
{  
   public string ExtendedSystemProp {get;set;}

   public override void GetPropertyInformation()
   {
      base.GetPropertyInformation();

      var prop = "some extra calculating";

      GetExtraPropertyInformation(prop);
    }

    public void GetExtraPropertyInformation(string prop)
    {
         ExtendedSystemProp = prop;
    }
}

ISystem genericSystem = new B();
genericSystem.GetPropertyInformation();

(genericSystem as B).ExtendedSystemProp = "value";
3 голосов
/ 29 сентября 2011

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

Что касается переопределения метода и изменения списка параметров, это просто невозможно. Представьте, как бы вы вызвали этот метод для базового класса или ссылки на интерфейс?

2 голосов
/ 29 сентября 2011

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

2 голосов
/ 29 сентября 2011

Другие рассказали о том, что изначально было в моем ответе, но о «добавлении параметра»: не забывайте, что последний C # также позволяет вам иметь дополнительные параметры в методах.

2 голосов
/ 29 сентября 2011

Нельзя передать дополнительный параметр в переопределении. Когда вы переопределяете, вы переопределяете метод с точной подписью. Я бы посоветовал вам передать параметр интерфейса, например IPropertyInformation, который может меняться для каждой реализации.

Решение использовать базовый класс или интерфейс для вашей реализации действительно зависит от вашего использования. Достаточно ли общего у A-I друг с другом, чтобы все они действительно происходили из одного базового класса? Если так, то используйте базовый класс. Действительно ли это просто GetPropertyInformation, и в противном случае системы полностью отличаются друг от друга? Тогда вы действительно хотите, чтобы они поделились интерфейсом.

...