Интерфейс, аннотация или просто виртуальные методы?
У меня есть куча систем, давайте называть их 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
является общим и в противном случае системы полностью функционально отличаются? Тогда вы действительно хотите, чтобы они поделились интерфейсом.