Полиморфизм и уныние вопросы
Я читаю книгу о Java и в настоящее время на Polymorphism
тема, а также как downcast
ссылочная переменная. Тем не менее, я застрял в понимании концепции уныния. Ниже приведен пример для примера, которому я следую.
Для всех объектов BasePlusCommissionEmployee
они должны увеличить свою базовую зарплату на 10%. Другой Employee
подклассы в соответствии с нормой. PayrollSystemTest
содержит основной метод для запуска приложения.
// Fig. 10.9: PayrollSystemTest.java
// Employee hierarchy test program.
public class PayrollSystemTest
{
public static void main(String[] args)
{
// create subclass objects
SalariedEmployee salariedEmployee =
new SalariedEmployee("John", "Smith", "111-11-1111", 800.00);
HourlyEmployee hourlyEmployee =
new HourlyEmployee("Karen", "Price", "222-22-2222", 16.75, 40.0);
CommissionEmployee commissionEmployee =
new CommissionEmployee(
"Sue", "Jones", "333-33-3333", 10000, .06);
BasePlusCommissionEmployee basePlusCommissionEmployee =
new BasePlusCommissionEmployee(
"Bob", "Lewis", "444-44-4444", 5000, .04, 300);
System.out.println("Employee processed individually:");
System.out.printf("%n%s%n%s: $%,.2f%n%n",
salariedEmployee, "earned", salariedEmployee.earnings());
System.out.printf("%s%n%s: $%,.2f%n%n",
hourlyEmployee, "earned", hourlyEmployee.earnings());
System.out.printf("%s%n%s: $%,.2f%n%n",
commissionEmployee, "earned", commissionEmployee.earnings());
System.out.printf("%s%n%s: $%,.2f%n%n",
basePlusCommissionEmployee,
"earned", basePlusCommissionEmployee.earnings());
// create four-element Employee array
Employee[] employees = new Employee[4];
// initialize array with Employees
employees[0] = salariedEmployee;
employees[1] = hourlyEmployee;
employees[2] = commissionEmployee;
employees[3] = basePlusCommissionEmployee;
System.out.printf("Employees processed polymorphically:%n%n");
// generically process each element in array employees
for (Employee currentEmployee : employees)
{
System.out.println(currentEmployee); // invokes toString
// determine whether element is a BasePlusCommissionEmployee
if (currentEmployee instanceof BasePlusCommissionEmployee)
{
// downcast Employee reference to
// BasePlusCommissionEmployee reference
BasePlusCommissionEmployee employee =
(BasePlusCommissionEmployee) currentEmployee;
employee.setBaseSalary(1.10 * employee.getBaseSalary());
System.out.printf(
"new base salary with 10%% increase is: $%,.2f%n",
employee.getBaseSalary());
} // end if
System.out.printf(
"earned $%,.2f%n%n", currentEmployee.earnings());
} // end for
// get type name of each object in employees array
for (int j = 0; j < employees.length; j++)
System.out.printf("Employee %d is a %s%n", j,
employees[j].getClass().getName());
} // end main
} // end class PayrollSystemTest
В книге также объясняется, что расширенный цикл for выполняет итерацию массива. employees
и вызывает методы toString
а также earnings
с Employee
переменная currentEmployee
которому присваивается ссылка на другой Employee
в массиве на каждой итерации. В результате выходные данные показывают, что конкретные методы для каждого класса вызываются и разрешаются во время выполнения в зависимости от типа объекта.
Для того, чтобы вызвать BasePlusCommissionEmployee
методы getBaseSalary
а также setBaseSalary
на текущий Employee
объект, оператор условия используется для проверки, является ли ссылка на объект BasePlusCommissionEmployee
объект с помощью оператора instanceof и если условие истинно, объект должен быть понижен с Employee
в BasePlusCommissionEmployee
введите перед вызовом упомянутых методов.
Это серьезно смущает меня, потому что мы можем получить доступ к подклассам toString
метод, но должен уменьшить объект, чтобы использовать другие методы, а именно getBaseSalary
а также setBaseSalary
? Почему это так?
3 ответа
Так как toString()
определяется в Object
поэтому доступны в каждом классе. Геттер и сеттер для базовой зарплаты доступны только в BasePlusCommissionEmployee
так что вы не можете позвонить через Employee
ссылка (что произойдет, если он ссылается на другой тип?).
Этот пример не тот, который вы видели бы в реальном коде. Использование instanceof для определения плохого стиля.
Когда вы хотите вызвать метод для экземпляра, методы, которые вы можете вызвать, зависят от нескольких вещей, среди объявленного типа экземпляра, модификатора метода и от того, откуда вы их вызываете.
В вашем примере это объявленный тип экземпляра, который должен вас заинтересовать.
Например, когда вы объявляете это:
String s = new String("string");
Вы можете вызывать доступные методы из String
учебный класс.
Например:
s.toString();
s.trim();
etc...
В вашем случае, когда вы заявляете это:
BasePlusCommissionEmployee basePlusCommissionEmployee =
new BasePlusCommissionEmployee(
"Bob", "Lewis", "444-44-4444", 5000, .04, 300);
Employee currentEmployee = basePlusCommissionEmployee;
ты можешь сделать:basePlusCommissionEmployee.getBaseSalary()
поскольку BasePlusCommissionEmployee
объявленный тип предоставляет метод для.
Вы также можете сделать:basePlusCommissionEmployee.toString()
а также currentEmployee.toString()
потому что оба типа (Employee
а также BasePlusCommissionEmployee
) предоставить метод для toString()
потому что метод является публичным методом из Object
класс и все классы наследуются от Object
класс, так что эти классы имеют toString()
метод.
Но вы не можете сделать:currentEmployee.getBaseSalary()
поскольку Employee
объявленный тип не предоставляет метод для.
Чтобы обойти это, вы можете выполнить переход от базового класса к целевому дочернему классу:
Employee currentEmployee = basePlusCommissionEmployee;
((BasePlusCommissionEmployee)currentEmployee).getBaseSalary();
Стоит добавить в моих глазах: это на самом деле довольно плохой пример.
Удручение очень часто является признаком плохого дизайна; и это хорошо доказывает это правило.
Эта система начисления заработной платы не должна нуждаться в такой проверке "instanceof"; затем сделать некоторые конкретные вычисления для определенного подкласса.
В этом весь смысл использования полиморфизма: каждый из этих различных классов BasePlusCommissionEmployee и CommissionEmployee должен содержать средства для правильного расчета правильного оклада.
В данном случае следует придерживаться принципа TDA (не говорите). Хороший ОО говорит о том, что какой-то объект "делает вещь"; вместо того, чтобы просить объект о чем-либо, затем принять внешнее решение на основе этого внутреннего состояния (или природы в данном случае) этого объекта!
Для всех, кто интересуется пониманием того, как на самом деле решить эту проблему, я предлагаю изучить "Гибкие принципы" Роберта Мартина. Эта книга описывает разработку / внедрение реальной системы начисления заработной платы...