float currPay, string ssn, int numbOfOpts)
{
// Это свойство определено в классе Manager.
StockOptions = numbOfOpts;
// Присвоить входные параметры, используя
// унаследованные свойства родительского класса.
Id = empId;
Age = age;
Name = fullName;
Pay = currPay;
PayType = EmployeePayTypeEnum.Salaried;
// Если свойство SSN окажется доступным только для чтения,
// тогда здесь возникнет ошибка на этапе компиляции!
SocialSecurityNumber = ssn;
}
Первая проблема с таким подходом связана с тем, что если любое свойство определено как допускающее только чтение (например, свойство SocialSecurityNumber
string
данному полю не удастся, как можно видеть в финальном операторе специального конструктора.Вторая проблема заключается в том, что был косвенно создан довольно неэффективный конструктор, учитывая тот факт, что в C# стандартный конструктор базового класса вызывается автоматически перед выполнением логики конструктора производного класса, если не указано иначе. После этого момента текущая реализация имеет доступ к многочисленным открытым свойствам базового класса Employee
Manager
на самом деле выполнялось восемь действий (обращения к шести унаследованным свойствам и двум конструкторам).Для оптимизации создания объектов производного класса необходимо корректно реализовать конструкторы подкласса, чтобы они явно вызывали подходящий специальный конструктор базового класса вместо стандартного конструктора. Подобным образом можно сократить количество вызовов инициализации унаследованных членов (что уменьшит время обработки). Первым делом обеспечьте наличие в родительском классе Employee
// Добавление в базовый класс Employee.
public Employee(string name, int age, int id, float pay, string empSsn,
EmployeePayTypeEnum
payType)
{
Name = name;
Id = id;
Age = age;
Pay = pay;
SocialSecurityNumber = empSsn;
PayType = payType;
}
Модифицируйте специальный конструктор в классе Manager
Employee
с применением ключевого слова base
:public Manager(string fullName, int age, int empId,
float currPay, string ssn, int numbOfOpts)
: base(fullName, age, empId, currPay, ssn,
EmployeePayTypeEnum.Salaried)
{
// Это свойство определено в классе Manager.
StockOptions = numbOfOpts;
}
Здесь ключевое слово base
this
, как обсуждалось в главе 5), что всегда указывает производному конструктору на необходимость передачи данных конструктору непосредственного родительского класса. В рассматриваемой ситуации явно вызывается конструктор с шестью параметрами, определенный в Employee
, что избавляет от излишних обращений во время создания объекта дочернего класса. Кроме того, в класс Manager
добавлена особая линия поведения, которая заключается в том, что тип оплаты всегда устанавливается в Salaried
. Специальный конструктор класса SalesPerson
выглядит почти идентично, но только тип оплаты устанавливается в Commission
:// В качестве общего правила запомните, что все подклассы должны
// явно вызывать подходящий конструктор базового класса.
public SalesPerson(string fullName, int age, int empId,
float currPay, string ssn, int numbOfSales)
: base(fullName, age, empId, currPay, ssn,
EmployeePayTypeEnum.Commission)
{
// Это принадлежит нам!
SalesNumber = numbOfSales;
}