Параметры и наследование конструктора
Новый для ООП, и я смущен тем, как конструкторы производного класса работают при наследовании от базового класса в С#.
Сначала базовый класс:
class BaseClass
{
private string BaseOutput = null;
public BaseClass(string BaseString)
{
BaseOutput = BaseString;
}
public virtual void PrintLine()
{
Console.WriteLine(BaseOutput);
}
}
Вот производный класс:
class SubClass : BaseClass
{
private string SubOutput = null;
public SubClass(string BaseString, string SubString) : base(BaseString)
{
SubOutput = SubString;
}
public override void PrintLine()
{
Console.WriteLine(SubOutput);
}
}
Наконец, основная часть программы:
class Program
{
static void Main(string[] args)
{
BaseClass theBase = new BaseClass("Text for BaseClass");
SubClass theSub = new SubClass("2nd param", "Text for SubClass");
theBase.PrintLine();
theSub.PrintLine();
Console.ReadKey();
}
}
Я не понимаю, почему при вызове конструктора для производного класса я должен также передать параметр, который нужен базовому классу. Разве поле BaseOutput в производном классе не должно оставаться равным null, если ему не присвоено значение? Почему не может быть что-то вроде этой работы:
public SubClass(string SubString) : base(BaseString)
Кроме того, при вызове конструктора в этом производном классе первый параметр должен быть назван тем же, что и в базовом классе, иначе он выдает ошибку. Если бы я должен был определить новую строковую переменную с именем AnotherString в производном классе, почему бы не работать:
public SubClass(string AnotherString, string SubString) : base(BaseString)
Наконец, когда вы сделаете это правильно и введите это...
public SubClass(string BaseString, string SubString) : base(BaseString)
... Каков первый параметр в используемом конструкторе SubClass? Он не назначается или не используется ни в каких методах для моего производного класса. Почему я вообще должен его там даже поставить?
Ответы
Ответ 1
Что вы не можете сделать:
public SubClass(string SubString) : base(BaseString)
Что было бы BaseString
?
Вы можете сделать:
public SubClass(string SubString) : base("SomeFixedString")
или
public SubClass(string SubString) : base(SubString)
Но если вы хотите передать одну строку в параметр конструктора базового класса и иметь дополнительный, вам нужно принять два параметра.
Что касается сохранения одного и того же имени, вы этого не делаете. Вы можете сделать:
public SubClass(string AnotherString, string SubString) : base(AnotherString)
Что касается последнего вопроса, первый параметр ничего не делает, он передается конструктору базового класса. Вы можете использовать его для чего-то еще, если хотите.
Ответ 2
Если вы хотите инициализировать BaseString
значением по умолчанию, передайте это значение конструктору базового класса (таким образом, вам не нужно передавать этот параметр в конструктор производного класса)
public SubClass(string SubString) : base(null)
Или определить конструктор без параметров в базовом классе.
Также о присвоении параметров - не имеет значения, какое имя имеет параметр, который вы передаете производному конструктору. Единственное, что имеет значение, это значение, которое вы передаете базовому конструктору.
public SubClass(string AnotherString, string SubString) : base(AnotherString)
Ответ 3
public SubClass(string BaseString, string SubString) : base(BaseString)
Этот конструктор в производном классе говорит, что когда вы получаете два аргумента BaseString
и SubString
, вызовите конструктор базового класса с BaseString
.
Таким образом, делая
public SubClass(string a, string b) : base(BaseString)
не работает, потому что вы говорите ему, чтобы вызвать конструктор базового класса с BaseString
, но нет аргумента, называемого BaseString
.
Если вы хотите создать экземпляр производного класса, не передавая String в конструктор базового класса, базовому классу нужен конструктор по умолчанию:
public BaseClass() { }
Ответ 4
Если вы хотите предоставить возможность производному классу NOT установить BaseString, вам необходимо предоставить конструктор по умолчанию в базовом классе следующим образом:
public BaseClass()
{
}
Теперь в производном классе вы можете вызвать конструктор без аргументов в базовом классе следующим образом:
public SubClass(string AnotherString)
: base()
{
// base() => explicit call to default construct in the base class.
// Do something else
}
Это обеспечивает хорошую практику разработки программного обеспечения: если вы хотите предоставить возможность не устанавливать строку базового класса, тогда сделайте это в базовом классе. Другие "хаки", подобные передаче null в качестве аргумента базовому конструктору, служат только для того, чтобы возиться с внутренними элементами базового класса способами, которые не должны выполняться из подклассов.