На этом шаге мы рассмотрим пример использования абстрактных классов
Приведем текст программы, в которой определены один абстрактный суперкласс Person и два подкласса Employee и Student.
Исходный код класса PersonTest
/** * <p>Класс для тестирования программы</p> * */ public class PersonTest { public static void main(String[] args) { Person[] people = new Person[2]; people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1); people[1] = new Student("Maria Morris", "computer science"); for (Person person : people) { System.out.println(person.getName() + ", " + person.getDescription()); } } }
Исходный код класса Person
/** * <p>Абстрактный класс Person</p> * */ abstract public class Person { public abstract String getDescription(); private String name; /** * <p>Конструктор класса Person</p> * @param name Имя человека * */ public Person(String name) { this.name = name; } /** * <p>Функция возвращает имя человека</p> * @return Имя человека * */ public String getName() { return name; } }
Исходный код класса Employee
import java.util.Date; import java.util.GregorianCalendar; /** *<p>Класс Employee, который наследуется от класса Person</p> * */ public class Employee extends Person { private double salary; private Date hireDay; /** * <p>Конструктор класса Employee.</p> * <p>Вначале происходит вызов конструтор класса родителя * для записи имени сотрудника</p> * @param name Имя сотрудника * @param salary Заработная плата * @param year Год начала работы * @param month Месяц начала работы * @param day День начала работы * */ public Employee(String name, double salary, int year, int month, int day) { super(name); this.salary = salary; GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day); this.hireDay = calendar.getTime(); } /** * <p>Функция возвращает заработную плату</p> * @return Заработная плата * */ public double getSalary() { return salary; } /** * <p>Функция возвращает день устройтва на работу</p> * @return День устройтва на работу * */ public Date getHireDay() { return hireDay; } /** * <p>Функция предоставляет отчет - какова зарплата сотрудника</p> * @return Отчет о заработной плате сотрудника * */ @Override public String getDescription() { return String.format("an employee with a salary of $%.2f", salary); } /** * <p>Функция для увеличения заработной платы сотрудника * на заданое количество процентов</p> * @param byPercent Количество процентов * */ public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
Исходный код класса Student
/** * <p>Класс Student, который наследуется от класса Person</p> * */ public class Student extends Person { private String major; /** * <p>Конструктор класса Student</p> * <p>Вначале происходит вызов конструтор класса родителя * для записи имени студента</p> * @param name Имя студента * @param major Профилирующий предмет * */ public Student(String name, String major) { super(name); this.major = major; } /** * <p>Функция предоставляет отчет - какой профилирующий предмет студента</p> * @return Отчет о профилирующим предмете студента * */ @Override public String getDescription() { return "a student majoring in " + major; } }
Проект можно взять здесь
Рис. 1. Вывод программы
Следует иметь в виду, что переменная person цикла вообще не ссылается ни на один из объектов абстрактного класса Person, поскольку создать такой объект просто невозможно. Переменная Person ссылается на объект конкретного подкласса, например Employee или Student.
Может возникнуть следующий вопрос: Можно ли пропустить в классе Person все абстрактные методы и определить метод getDescription() в подклассах Employee и Student? Ответ простой, это не будет ошибкой, но тогда метод getDescription() нельзя будет вызвать с помощью переменной person. Компилятор гарантирует, что вызываются только те методы, которые определены в классе.
Абстрактные методы являются важным понятием языка Java. Они в основном применяются при создании интерфейсов (с интерфейсами мы познакомимся позднее).
На следующем шаге мы рассмотрим доступ к данным