Интерфейс, аннотация или просто виртуальные методы?

У меня есть куча систем, давайте называть их 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 ответов

Решение

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

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

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

А также System не такое хорошее имя.

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

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

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

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

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";

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

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

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

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

Другие вопросы по тегам