Абстрактный класс с конструктором, заставить унаследованный класс вызывать его
Возможно, дубликат, у меня есть абстрактный класс с конструктором XYZ (имя строки). Также у меня есть класс, который наследует от этого абстрактного класса. Как заставить унаследованный класс вызывать базу (имя строки)? Теперь я могу использовать новый Inherited(), и он не будет вызывать базовую конструкцию. Я хочу заставить пользователя реализовать конструктор по умолчанию в унаследованном классе.
4 ответа
Класс без явного конструктора имеет конструктор без параметров. С другой стороны, если вы реализуете конструктор с параметрами и без беспараметрического конструктора, ваш класс не будет создан без аргументов.
Другими словами:
public abstract class A
{
public A(string x)
{
}
}
public class B : A
{
// If you don't add ": base(x)"
// your code won't compile, because A has a
// constructor with parameters!
public B(string x) : base(x)
{
}
}
То есть если A
имеет конструктор без параметров (или без явного конструктора), B
автоматически вызовет базовый конструктор. Вам не нужно кодировать дальнейшие вещи здесь.
В противном случае, если ваш базовый класс имеет конструктор без параметров и конструктор с параметрами, вы не можете заставить производный класс автоматически вызывать конструктор, исключая конструктор по умолчанию (то есть так называемый конструктор без параметров).
Временное решение
Ну, здесь нет особого обходного пути, но имейте в виду, что C# поддерживает необязательные параметры как в конструкторах, так и в методах.
Если вы хотите быть на 100% уверены, что производные классы будут вызывать конкретный базовый конструктор, вы можете реализовать свой базовый класс, используя один конструктор без параметров с необязательными параметрами, и использовать его вместо перегрузки конструктора:
public class A
{
public A(string x = "hello world") // or just string x = null
{
}
}
Теперь, если B
производный класс A
, B
всегда буду звонить A
конструктор, т.к. x
не является обязательным и имеет значение по умолчанию.
Как заставить унаследованный класс вызывать
base(string name)
Сделайте конструктор без параметров в вашем абстрактном классе приватным или не добавляйте его вообще. Это заставит все производные классы вызывать указанный вами конструктор, иначе произойдет ошибка компиляции.
public abstract class BaseClass
{
protected BaseClass(string parameter)
{
}
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
}
}
В конечном итоге
'`Project.BaseClass`' does not contain a constructor that takes 0 arguments
Вам не нужно ничего делать. Все конструкторы производного класса должны вызывать конструктор базового класса (за исключением некоторых особенно злых хаков, о которых вам, вероятно, не нужно беспокоиться). Если в коде явно не указано ни одного, подразумевается неявный вызов конструктора без параметров базового класса. Если базовый класс не имеет конструктора без параметров (как в случае, если вы добавляете конструктор, принимающий строку, и не добавляете конструктор без параметров), класс не будет компилироваться.
Я провел последние полчаса или около того, экспериментируя еще раз с перестановками абстрактного базового класса, конструктор по умолчанию которого помечен как закрытый, и перегрузкой, которая принимает 4 параметра, и производным классом, который имеет только перегрузку из 4 параметров. Используя последний компилятор C# (7.3), очевидно, что в этой ситуации:
- Производный класс должен явно определять перегрузку с 4 параметрами.
- Перегрузка в вызове производного класса для перегрузки с 4 параметрами должна быть явной.
Подпись конструктора базового класса
public OperatingParameterBase (
string pstrInternalName ,
string pstrDisplayName ,
T penmParameterType ,
U penmDefaultParameterSource )
Конструктор производного класса
internal OperatingParameter (
string pstrInternalName ,
string pstrDisplayName ,
T penmParameterType ,
U penmDefaultParameterSource )
: base (
pstrInternalName ,
pstrDisplayName ,
penmParameterType ,
penmDefaultParameterSource )
{
} // internal OperatingParameterExample constructor
Я показал весь конструктор в производном классе, чтобы продемонстрировать, что вызов конструктора базового класса является его единственным абсолютным требованием. Поскольку работа базового конструктора не имеет отношения к этому обсуждению, я оставил это в стороне.