Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

}

}

public class Detergent extends Cleanser { II Изменяем метод-public void scrubO {

appendC' Detergent.scrubO").

super scrubO, // Вызываем метод базового класса

}

11 Добавляем новые методы к интерфейсу public void foamO { appendC foamO"), } // Проверяем новый класс, public static void main(String[] args) { Detergent x = new DetergentO, x.diluteO, x.applyO, x scrubO; x. foamO; print(x);

print("Проверяем базовый класс"); Cleanser main(args);

}

} /* Output

Cleanser diluteO applyO Detergent.scrub scrubO foamO Проверяем базовый класс Cleanser diluteO applyO scrubO */// ~

Пример

демонстрирует сразу несколько особенностей наследования. Во-первых, в методе класса Cleanser append новые строки присоединяются к строке s оператором += — одним из операторов, специально «перегруженных» создателями Java для строк (String).

Во-вторых, как Cleanser, так и Detergent содержат метод main. Вы можете определить метод main в каждом из своих классов; это позволяет встраивать тестовый код прямо в класс. Метод main даже не обязательно удалять после завершения тестирования, его вполне можно оставить на будущее.

Даже если у вас в программе имеется множество классов, из командной строки исполняется только один (так как метод main всегда объявляется как public, то неважно, объявлен ли класс, в котором он описан, как public). В нашем примере команда java Detergent вызывает метод Detergent.mainQ. Однако вы также можете использовать команду java Cleanser для вызова метода Cleanser.main, хотя класс Cleanser не объявлен открытым. Даже если класс обладает доступом в пределах класса, открытый метод main остается доступным.

Здесь метод Detergent.main вызывает Cleanser.main явно, передавая ему собственный массив аргументов командной строки (впрочем, для этого годится любой массив строк).

Важно, что все методы класса Cleanser объявлены открытыми. Помните, что при отсутствии спецификатора доступа, член класса автоматически получает доступ «в пределах пакета», что позволяет обращаться к нему только из текущего пакета. Таким образом, в пределах данного пакета при отсутствии спецификатора доступа вызов этих методов разрешен кому угодно — например, это легко может сделать класс Detergent. Но если бы какой-то класс из другого пакета был объявлен производным от класса Cleanser, то он получил бы доступ только к его public-членам. С учетом возможности наследования все поля обычно помечаются как private, а все методы — как public. (Производный класс также получает доступ к защищенным (protected) членам базового класса, но об этом позже.) Конечно, иногда вы будете отступать от этих правил, но в любом случае полезно их запомнить.

Класс Cleanser содержит ряд методов: append, dilute, apply, scrub и toString. Так как класс Detergent произведен от класса Cleanser (с помощью ключевого слова extends), он автоматически получает все эти методы в своем интерфейсе, хотя они и не определяются явно в классе Detergent. Таким образом, наследование обеспечивает повторное использование класса.

Как показано на примере метода scrub, разработчик может взять уже существующий метод базового класса и изменить его. Возможно, в этом случае потребуется вызвать метод базового класса из новой версии этого метода. Однако в методе scrub вы не можете просто вызвать scrub — это приведет к рекурсии, а нам нужно не это. Для решения проблемы в Java существует ключевое слово super, которое обозначает «суперкласс», то есть класс, производным от которого является текущий класс. Таким образом, выражение super.scrub обращается к методу scrub из базового класса.

При наследовании вы не ограничены использованием методов

базового класса. В производный класс можно добавлять новые методы тем же способом, что и раньше, то есть просто определяя их. Метод foam — наглядный пример такого подхода.

В методе Detergent.main для объекта класса Detergent вызываются все методы, доступные как из класса Cleanser, так и из класса Detergent (имеется в виду метод foam).

Инициализация базового класса

Так как в наследовании участвуют два класса, базовый и производный, не сразу понятно, какой же объект получится в результате. Внешне все выглядит так, словно новый класс имеет тот же интерфейс, что и базовый класс, плюс еще несколько дополнительных методов и полей. Однако наследование не просто копирует интерфейс базового класса. Когда вы создаете объект производного класса, внутри него содержится подобъект базового класса. Этот подобъект выглядит точно так же, как выглядел бы созданный обычным порядком объект базового класса. Поэтому извне представляется, будто бы в объекте производного класса «упакован» объект базового класса.

Конечно, очень важно, чтобы подобъект базового класса был правильно инициализирован, и гарантировать это можно только одним способом: выполнить инициализацию в конструкторе, вызывая при этом конструктор базового класса, у которого есть необходимые знания и привилегии для проведения инициализации базового класса. Java автоматически вставляет вызовы конструктора базового класса в конструктор производного класса. В следующем примере задействовано три уровня наследования:

//: reusing/Cartoon.java

// Вызовы конструкторов при проведении наследования, import static net.mindview.util.Print.*,

class Art {

ArtO { print("Конструктор Art"); }

}

class Drawing extends Art {

DrawingО { print("Конструктор Drawing"); }

}

public class Cartoon extends Drawing {

public CartoonO { print("Конструктор Cartoon"); } public static void main(String[] args) { Cartoon x = new CartoonO;

}

} /* Output; Конструктор Art Конструктор Drawing Конструктор Cartoon * ///:-

Как видите, конструирование начинается с «самого внутреннего» базового класса, поэтому базовый класс инициализируется еще до того, как он станет доступным для конструктора производного класса. Даже если конструктор класса Cartoon не определен, компилятор сгенерирует конструктор по умолчанию, в котором также вызывается конструктор базового класса.

Конструкторы с аргументами

В предыдущем примере использовались конструкторы по умолчанию, то есть конструкторы без аргументов. У компилятора не возникает проблем с вызовом таких конструкторов, так как вопросов о передаче аргументов не возникает. Если класс не имеет конструктора по умолчанию или вам понадобится вызвать конструктор базового класса с аргументами, этот вызов придется оформить явно, с указанием ключевого слова super и передачей аргументов:

//: reusing/Chess.java

// Наследование, конструкторы и аргументы.

import static net.mindview.util.Print.*;

class Game {

Game(int i) {

print("Конструктор Game"),

}

}

class BoardGame extends Game { BoardGame(int i) { super(i);

print("Конструктор BoardGame");

}

}

public class Chess extends BoardGame { Chess О {

super(ll);

print("Конструктор Chess");

}

public static void main(String[] args) { Chess x = new ChessO:

Поделиться:
Популярные книги

Эволюция мага

Лисина Александра
2. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эволюция мага

Искатель 1

Шиленко Сергей
1. Валинор
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Искатель 1

Хозяйственная помощница для идеала

Свободина Виктория
15. Помощница
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Хозяйственная помощница для идеала

Прометей: каменный век II

Рави Ивар
2. Прометей
Фантастика:
альтернативная история
7.40
рейтинг книги
Прометей: каменный век II

Как я строил магическую империю 7

Зубов Константин
7. Как я строил магическую империю
Фантастика:
попаданцы
постапокалипсис
аниме
фантастика: прочее
5.00
рейтинг книги
Как я строил магическую империю 7

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

Случайная жена для лорда Дракона

Волконская Оксана
Фантастика:
юмористическая фантастика
попаданцы
5.00
рейтинг книги
Случайная жена для лорда Дракона

Часовое имя

Щерба Наталья Васильевна
4. Часодеи
Детские:
детская фантастика
9.56
рейтинг книги
Часовое имя

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

Начальник милиции. Книга 4

Дамиров Рафаэль
4. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 4

Черный Маг Императора 12

Герда Александр
12. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 12

Дочь опальной герцогини

Лин Айлин
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Дочь опальной герцогини

Маленькая слабость Дракона Андреевича

Рам Янка
1. Танцы на углях
Любовные романы:
современные любовные романы
эро литература
5.25
рейтинг книги
Маленькая слабость Дракона Андреевича