Учебная страница курса биоинформатики,
год поступления 2010
ООП в Java: Наследование, абстрактные классы и методы.
Итак, мы разобрали, что класс – это, по сути, новый тип данных. Класс является шаблоном, по которому потом создаются объекты этого класса. В классе мы задаем переменные, которые должны быть у каждого объекта данного класса. Также в классе мы определяем методы, которые задают функциональность объектов данного класса, то есть то, что должный уметь делать объекты данного класса (что-то вроде должностной инструкции). Часто при написании программ возникает необходимость сделать новый класс, который чем-то отличается от уже имеющегося. Например, SmallBoss.
В этом случае нам придется копировать весь код из класса Boss и дописывать новый метод playComputerGames. Это приводит к размножению одинакового кода. Причем, если в последствии Вы найдете ошибку в этом коде, ее надо будет исправить в нескольких местах. Это неудобно. Поэтому, в Java есть механизм наследования. Мы можем сделать класс SmallBoss наследником класса Boss:
Все объекты нового класса SmallBoss имеют те же переменные и методы, что и объекты класса Boss, плюс еще свой собственный метод playComputerGames(). Еще говорят, что класс SmallBoss расширяет класс Boss. Можно определить лишь один суперкласс для класса, который вы создаете. В нашей задаче про офис можно заметить, что классы Boss и Secretary содержат некоторое количество одинаковых полей и методов. Можно оптимизировать этот код при помощи наследования. Зададим класс Human и вынесем в него эти переменные и методы, а затем отнаследуем классы Boss и Secretary от класса Human.
1 public class Human {
2
3 String name;
4 String surname;
5
6 Human(String name, String surname)
7 {
8 this.name = name;
9 this.surname = surname;
10 }
11 String getFullName()
12 {
13 return name+" "+surname;
14 }
15 void speak(String phrase)
16 {
17 System.out.println(getFullName()+":\t-"+phrase);
18 }
19
20 }
Теперь отнаследовав класс , например, Secretary от Human, мы автоматически имеем в этом классе переменные name и surname и методы getFullName() speak().
Возникает одна тонкость с конструктором. Конструктор класса-наследника должен вызывать конструктор супер-класса, чтобы заполнить отнаследованные переменные.
Теперь, при создании объекта типа Secretary вначале вызывается конструктор супер-класса и заполняются переменные name и surname, а затем присваивается значение переменной nails_length. Ключевое слово super. Ключевое слово super используется для обращения не только к конструкторам суперкласса, но и к его методам. Чем-то похоже на this – только this обращается к методам данного класса, а super – родительского. Это используется, когда какие-то имена методов подкласса и суперкласса совпадают. А зачем это нужно? В случае наследования методы суперкласса уже определены, однако иногда наследник должен немного их изменить. например у нас Human имеет метод getFullName однако у босса мы бы хотели чтобы он добавлял к имени слово mr. а у секретарши miss, тогда мы можем переопределить (или еще говорят перегрузить) эти методы в наследнике:
При этом для получения собственно имени мы вызываем метод суперкласса. Еще одна особенность. Переменная суперкласса может ссылаться на объект подкласса, например,
Но у переменной типа Human нельзя вызвать метод, который определен в Secretary, но не определен в Human:
То есть, то, к каким элементам можно обращаться, определяется типом ссылки, а не типом объекта, на который она ссылается. А вот, какой код будет выполняться при вызове метода (если он перегружен) — зависит уже от типа объекта. Зачем это надо? Например, вы хотите создать массив и положить в него и боса и секретарш (например, список в отделе кадров). Тогда вы сделаете массив типа Human и смело можете класть туда объекты классов, наследующих от Human.
Маленькая задачка на понимание полиморфизма (перегрузки методов).
что напечатает программа? А так:
А так:
Явление, что классы с одинаковой спецификацией могут иметь различную реализацию, называется Полиморфизмом. Кратко смысл полиморфизма можно выразить фразой: Один интерфейс, множество реализаций.
Абстрактные классы и методы
В java суперклассы можно делать также абстрактыми. Делается с помощью слова abstract. Абстрактный класс служит для создания иерархии, объединения кода некоторой группы классов, которые будут от него наследовать. Невозможно создать объекты такого класса – он служит лишь как абстракция. Такие объекты были бы бесполезны, поскольку класс определен не полностью. В абстрактном классе можно определять абстрактные методы – методы без реализации. Реализованы они будут в классах-наследниках (подкласс должен обязательно переопределить их).
1 public abstract class Figure {
2 public int x;
3 public int y;
4 public int moveTo(int x, int y){
5 this.x = x;
6 this.y = y;
7 }
8 public abstract double getArea();
9 public abstract void print();
10 }
11 public class Square extends Figure {
12 public double double side;
13 public Square(int x, int y, double side) {
14 this.x = x;
15 this.y = y;
16 this.side=side;
17 }
18 public double getArea() {
19 return side*side;
20 }
21 }
22 public class Circle extends Figure {
23 public double radius;
24 public Circle(int x, int y, double radius) {
25 this.x = x;
26 this.y = y;
27 this.radius=radius;
28 }
29 public double getArea() {
30 return Math.PI*radius*radius;
31 }
32 }