На этом шаге мы начнем говорить об наследовании
Допустим, вы работаете в организации, где работа руководящего состава учитывается иначе, чем работа остальных сотрудников. Руководящим и обычным сотрудникам выплачивается заработная плата, но первые за свои достижения получают еще и премии. В таком случае для расчета зарплаты следует применять наследование, так как нужно определить новый класс Manager, в который придется ввести новые функциональные возможности. Но в этот класс можно перенести кое-что из того, что уже запрограммировано в классе Employee, сохранив все поля, определенные в исходном классе. Ниже показано, как определяется класс Manager, производный от класса Employee. Для обозначения наследования в Java служит ключевое слово extends.
class Manager extends Employee { ... }
Ключевое слово extends означает, что на основе существующего класса создается новый. Существующий класс называется суперклассом, базовым или родительским, а вновь создаваемый - подклассом, производным или порожденным.
Добавим в класс Manager новое поле, в котором будет храниться величина премии, а также новый метод, позволяющий задавать эту величину:
class Manager extends Employee { private double bonus; ... public void setBonus(double bonus){ this.bonus = bonus; } }
Заметим, что для объекта типа Employee вызывать метод setBonus() нельзя, поскольку его нет среди методов, определенных в классе Employee. Но в то же время методы getName() и getHireDay() можно вызвать из объектов типа Manager, поскольку они наследуются от суперкласса Employee, хотя и не определены в классе Manager.
Заметим, что метод getSalary() уже не подходит для подкласса Manager, так как должен возвращать сумму основной зарплаты и премии. Следовательно, нужно переопределить метод, то есть реализовать новый метод, замещающий соответствующий метод из суперкласса.
class Manager extends Employee { ... public double getSalary() { ... } ... }
Но методы класса Manager не имеют доступа к закрытым полям класса Employee. Поэтому нужно добиться вызова метода getSalary(), который определен в классе Employee. Для этой цели служит специальное ключевое слово super. Это слово сообщает компиляру, что нужно вызвать метод из суперкласса. Ниже представлен правильный вариант метода getSalary() для класа Manager.
public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; }
Как видите, в подкласс можно вводить поля, а также вводить и переопределять методы суперкласса. И в результате наследования ни одно поле или метод из класса не удаляется.
Добавим в класс Manager конструктор, как это показано ниже:
public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); bonus = 0; }
Здесь ключевое слово super имеет уже другой смысл. Оно означает вывзов конструктора суперкласса. Конструктор класса Manager не имеет доступа к закрытым полям класса Employee, и поэтому он должен инициализировать их, вызывая другой конструктор с помощью ключевого слова super. Вызов, содержащий обращение super, должен быть первым оператором в конструкторе подкласса. Если конструктор подкласса не вызывает явно ни одного из конструкторов суперкласса, то их этого суперкласса автоматически вызывается конструктор без аргументов. Если же в суперклассе отсутствует конструктор без аргументов, а конструктор подкласса не вызывает явно другой конструктор из суперкласса, то компилятор Java выдаст сообщение об ошибке.
На следующем шаге мы продолжим изучение этого вопроса