Я пытаюсь создать всеобъемлющий abstract
BaseClass
, который определяет способ создания всех производных классов, но позволяет производным классам специализировать/агрегировать поля и методы, используемые в процессе создания. Вот упрощенный пример:Определить методы конструктора базового класса в производных классах
public abstract class BaseClass
{
public List<String> list;
public BaseClass()
{
defineList();
optionalDoSomething();
doSomething();
}
protected void defineList()
{
list = new List<String>();
}
protected void doSomething()
{
// do something w/ list here
}
protected void optionalDoSomething() {}
}
public class DerivedClass : BaseClass
{
protected void defineList()
{
base.defineList();
list.Add("something");
}
public DerivedClass() : base() { }
}
public class SecondDerivedClass : DerivedClass
{
protected void defineList()
{
base.defineList();
list.Add("somethingElse");
}
protected void optionalDoSomething()
{
// do something special
}
public SecondDerivedClass() : base() { }
}
Это освободит все производные классы от того, чтобы воссоздать ту же логику инициализации, и каждый производный класс должен только «переписать» необходимые поля и методы, используемые в процессе создания (и, возможно, в другом месте класса).
Проблема:
Я не могу отметить
BaseClass
'методы, какvirtual
, так как вы не можете вызватьvirtual
методы базового конструктора (в любом случае, я не хотел бы использоватьvirtual
методы, поскольку, например, Я бы не хотел, чтобыDerivedClass
использовал методSecondDerivedClass
'defineList
).Я могу отметить их
abstract
, но тогда я не смог бы поставить «реализации по умолчанию» вBaseClass
, и каждый производный класс должен был бы реплицировать/реализовать эти значения по умолчанию. Кроме того, классSecondDerived
все равно должен был бы «переопределить» реализацииDerivedClass
.Не работает простое использование ключевого слова
new
«hide» менее производного класса.
Каков правильный способ получить этот шаблон?
TLDR: согласно мой комментарий ниже: Если BaseClass
является abstract
класс с методом A
и DerivedClass
является класс, производный от BaseClass
(не обязательно прямым потомком BaseClass
), то вызов A
в BaseClass
'конструктор должен вызвать A()
в каждом классе иерархии наследования до DerivedClass
(но не более). Мы можем предположить, что A
(вынужденный быть) определен на каждом промежуточном классе.
Я не очень понимаю ваш вопрос. Прежде всего, хотя, конечно же, не рекомендуется, законно вызывать виртуальных членов из конструктора. Во-вторых, в вашем примере единственное, что делают методы 'defineList()', это добавить элементы в поле 'list' (которое не должно быть' public', и, откровенно говоря, в большинстве сценариев будет ''private'_, а не даже 'protected'), что вы могли бы так же легко сделать в каждом конструкторе каждого класса. В других сценариях вы просто передадите инициализированные данные из более производных конструкторов вплоть до конструкторов базового класса. –
Я не буду называть 'virtual' методы в конструкторе. Кроме того, это упрощенный пример, но в целом методы, вызываемые в конструкторе 'BaseClass', могут делать другие вещи. В конечном счете, конструктор «BaseClass» должен «накапливать» некоторые данные, а затем вызывать методы, обрабатывающие эти данные. Поскольку обработка этих данных будет одинаковой для * большинства * производных классов, эти классы должны будут предоставить больше данных (например, 'defineList') до того, как будет вызываться метод обработки (например,' doSomething'). Разрешить производным классам «перезаписывать» другие методы не часто случаются. – jayflo
«методы, называемые конструктором BaseClass, могли бы делать другие вещи», - пожалуйста, укажите пример кода, который иллюстрирует эти «другие вещи». Поскольку вопрос задан до сих пор, все, что у вас есть, не проблема. Это, безусловно, приведет (и привело) к целому ряду попыток ответить, но, как вы можете видеть, предложения находятся вне пределов доски, и без явного заявления о проблемах трудно понять, как вопрос и ответы могут оказаться полезными в целом другим. –