Кен Арнольд Джеймс Гослинг

Вид материалаДокументы

Содержание


1.10. Расширение класса
1.10.1. Класс Object
1.10.2. Вызов методов суперкласса
Подобный материал:
1   2   3   4   5   6   7   8   9   10   ...   81

1.10. Расширение класса


Одним из самых больших достоинств объектно-ориентированного программирования является возможность такого расширения, или создания подкласса, существующего класса, при котором можно использовать код, написанный для исходного класса.

При расширении класса на его основе создается новый класс, наследующий все поля и методы расширяемого класса. Исходный класс, для которого проводилось расширение, называется суперклассом.

Если подкласс не переопределяет (override) поведение суперкласса, то он наследует все свойства суперкласса, поскольку, как уже говорилось, расширенный класс наследует поля и методы суперкласса.

Примером с плеерами Walkman можно воспользоваться и здесь. В последних моделях плееров устанавливаются два разъема для наушников, чтобы одну и ту же кассету могли слушать сразу двое. В объектно-ориентированном мире модель с двумя разъемами расширяет базовую модель. Эта модель наследует все характеристики и поведение базовой модели и добавляет к ним свои собственные.

Покупатели сообщали в корпорацию Sony, что они хотели бы иметь возможность разговаривать друг с другом во время прослушивания кассеты. Sony усовершенствовала свою модель с двумя разъемами, чтобы люди могли поговорить под музыку. Модель с двумя разъемами и с возможностью ведения переговоров является подклассом модели с двумя разъемами, наследует все ее свойства и добавляет к ним свои собственные.

У Sony имеются и другие модели плееров. Более поздние серии расширяют возможности базовой модели — они создают подклассы на ее основе и наследуют от нее свойства и поведение.

Давайте посмотрим, как происходит наследование в Java. Расширим наш класс Point, чтобы он представлял пиксель на экране монитора. В новом классе Pixel к координатам x и y добавляется информация о цвете пикселя:

class Pixel extends Point {

Color color;


public void clear() {

super.clear();

color = null;

}

}


Класс Pixel расширяет как данные, так и поведение своего суперкласса Point. Для данных это означает, что в классе Pixel появляется дополнительное поле color. Pixel также расширяет поведение Point, переопределяя метод clear класса Point. Эта концепция наглядно изображена на рисунке:



Объект Pixel может использоваться в любой программе, которая рассчитана на работу с объектами Point. Если методу необходимо передать параметр типа Point, можно вместо него передать объект Pixel — все будет нормально. Вместо объекта класса Point можно пользоваться объектом подкласса Pixel; это явление известно под названием “полиморфизм” — один и то же объект (Pixel) выступает в нескольких (поли-) формах (-морф) и может использоваться и как Pixel, и как Point.

Поведение Pixel расширяет поведение Point. Оно может совершенно преобразиться (например, работа с цветами в нашем примере) или будет представлять собой некоторое ограничение старого поведения, удовлетворяющее всем исходным требованиям. Примером последнего может служить объект класса Pixel, принадлежащий некоторому объекту Screen (экран), в котором значения координат x и y ограничиваются размерами экрана. В исходном классе Point значения координат могли быть произвольными, поэтому ограниченные значения координат все равно лежат в исходном (неограниченном) диапазоне.

Расширенный класс часто переопределяет поведение своего суперкласса (то есть класса, на основе которого он был создан), по-новому реализуя один или несколько унаследованных методов. В приведенном выше примере мы переопределили метод clear, чтобы он вел себя так, как того требует объект Pixel, — метод clear, унаследованный от Point, знает лишь о существовании полей Point, но, разумеется, не догадывается о присутствии поля color, объявленного в подклассе Pixel.

Упражнение 1.12

Напишите набор классов, отражающих структуру семейства плееров Sony Walkman. Воспользуйтесь методами, чтобы скрыть все данные, объявите последние с ключевым словом private, а методы — public. Какие методы должны принадлежать базовому классу Walkman? Какие методы добавятся в расширенных классах?

1.10.1. Класс Object


Классы, для которых не указан расширяемый класс, являются неявным расширением класса Object. Все ссылки на объекты полиморфно относятся к классу Object, который является базовым классом для всех ссылок, которые могут относиться к объектам любого класса:

Object oref = new Pixel();

oref = “Some String”;


В этом примере объекту oref вполне законно присваиваются ссылки на объекты Pixel и String, невзирая на то что эти классы не имеют между собой ничего общего — за исключением неявного суперкласса Object.

В классе Object также определяется несколько важных методов, рассмотренных в главе 3.

1.10.2. Вызов методов суперкласса


Чтобы очистка объектов класса Pixel происходила правильно, мы заново реализовали метод clear. Его работа начинается с того, что с помощью ссылки super вызывается метод clear суперкласса. Ссылка super во многих отношениях напоминает уже упоминавшуюся ранее ссылку this, за тем исключением, что super используется для ссылок на члены суперкласса, тогда как this ссылается на члены текущего объекта.

Вызов super.clear() обращается к суперклассу для выполнения метода clear точно так же, как он обращался бы к любому объекту суперкласса — в нашем случае, класса Point. После вызова super.clear() следует новый код, который должен присваивать color некоторое разумное начальное значение. Мы выбрали null — то есть отсутствие ссылки на какой-либо объект.

Что бы случилось, если бы мы не вызвали super.clear()? Метод clear класса Pixel присвоил бы полю цвета значение null, но переменные x и y, унаследованные от класса Point, остались бы без изменений. Вероятно, подобная частичная очистка объекта Pixel, при которой упускаются унаследованные от Point поля, явилась бы ошибкой в программе.

При вызове метода super.method() runtime-система просматривает иерархию классов до первого суперкласса, содержащего method(). Например, если бы метод clear отсутствовал в классе Point, то runtime-система попыталась бы найти такой метод в его суперклассе и (в случае успеха) вызвала бы его.

Во всех остальных ссылках при вызове метода используется тип объекта, а не тип ссылки на объект. Приведем пример:

Point point = new Pixel();


point.clear(); // используется метод clear() класса Pixel


В этом примере будет вызван метод clear класса Pixel, несмотря на то что переменная, содержащая объект класса Pixel, объявлена как ссылка на Point.