Конструктор базового класса всегда вызывается при создании экземпляра производного класса. Если базовый класс имеет конструктор по умолчанию, это будет вызов, если вы пропустите явный вызов конструктора базового класса.
* 1005 Е.Г. *
class Base
{
int x;
int y;
//default constructor
public Base()
{
x = -1;
y = -1;
}
public Base(int x, int y)
{
this.x = x;
this.y = y;
}
}
class Derived
{
public Derived()
{
}
}
это скомпилирует и установит поля экземпляра производного в -1 при создании производного объекта.
Однако если вы опустите конструктор по умолчанию, вы получите ошибку компиляции, подобную той, которую вы описали. Теперь компилятор не способен автоматически генерировать вызов базового конструктора. Я бы знал, какие параметры вызвать с
base(x=??,y=??)
Как правило, у вас должны быть открытые поля / свойства с одним и тем же именем, объявленными несколько раз, это почти всегда сильный запах проекта.
Если базовый класс имеет защищенное, внутреннее или открытое поле / свойство, то же относится и к производному классу (у внутреннего есть несколько странных случаев). Для методов вы можете скрыть реализацию mthod базового класса или переопределить его. Последнее является более распространенным и требует, чтобы базовое определение было абстрактным или виртуальным.
например,
//this requires Base to be declared abstract as well
public abstract void AbstractMethod();
public virtual void VirtualMethod(){}
, что позволяет писать следующим образом в классе DErived
public override void AbstractMethod(){}
public override void VirtualMethod(){}
Если вам нужно скрыть метод, вы можете сделать это, хотя это обычно не рекомендуется (см. Ниже, почему)
если вы просто повторно объявите метод, компилятор выдаст вам предупреждение, но вы можете использовать new, чтобы сообщить компилятору, что вы действительно хотите скрыть метод, он будет выглядеть следующим образом:
публичный новый void SomeHiddenMethod () {}
как бы то ни было это (потенциально) очень сильно влияет на использование объектов этого типа
public void SomeMEthod(Derived d)
{
//this calls the implementation in Derived
d.SomeHiddenMethod();
Base b = d;
//this calls the implementation in Base
b.SomeHiddenMethod();
}
сокрытие методов, таким образом, делает невероятно трудным рассуждать о коде, поскольку вызов одного и того же метода для одного и того же объекта может иметь разные результаты, даже если объект не изменил состояние между двумя вызовами, а просто потому, что объявленный тип переменная изменена.
И последнее замечание о наследовании, которое вы должны избегать наследования для функциональности, короче говоря, это просто потому, что вам нужны одинаковые функциональные возможности в двух (не связанных) классах, вы не должны создавать базовый класс для хранения этой функциональности, скорее вы должны создать третий класс, и инъекция, и экземпляр этого класса (или аналогичные подходы), и вы должны много думать о принципе замены Лискова при разработке открытого интерфейса класса, когда он не запечатан.