Главная » Java » Вызов методов базового класса Java

0

Чтобы снабдить объект рiхеl требуемыми функциями "очистки" своего внутреннего состояния, в классе Рiхе1 мы реализовали новую версию метода с1еаг, в теле которого посредством ссылки 5uper первым делом вызывается одноименный метод базового класса Роint. Ссылка 5uper во многом напоминает ссылку this, о которой МЫ говорили выше, за тем исключением, что 5uper позволяет адресовать элементы базового класса, а this ссылается на текущий объект.

Вызов super.clear() с точки зрения базового класса point выглядит как обычное обращение к методу сlеаг объекта Роint. После выполнения команды suрег.с1еаг()для очистки той части объекта Рiхеl, которая определена в Классе Роint, мы осуществляем дополнительную операцию присваивания ссылке сolог заведомо пустого и безопасного значения null.

Резонно спросить, что произойдет, не будь вызова super.сlеаr()? В этом Случае метод сlear класса рixel, разумеется, выполнит свою часть работы,

присвоив переменной соlor значение null о поля х и у, которые Рiхеl унаследовал от класса Роint, не получат каких бы то ни было "Чистых" значений. Если поля объекта – в том числе и те, которые объявлены в базовом Классе, ? остаются в состоянии, не отвечающем ситуации, это трудно не назвать явной ошибкой программиста.

При вызове super.тethod() Исполняющая система Java осуществляет просмотр иерархии классов в направлении от производных к базовым и пытается отыскать базовый класс, содержащий требуемый метод тethod. Если, например, класс Роint не содержал бы метода сlеаг, система перешла бы к классу, базовому по отношению к Роint, и т.д.

При вызове метода во внимание принимается класс объекта, но не тип ссылки на объект. Ниже приведен пример, иллюстрирующий сказанное.

Point point = new Рiхеl ();

point.clear(); // Вызывается метод сlеаг класса Рiхеl

Здесь программа обращается к методу Сlеаr класса Рiхеl, хотя переменная, содержащая объект Рiхеl, объявлена в Виде ссылки на объект класса Роint. Но если осуществить вызов super.сlеаг() из тела любого метода объекта Рiхеl, будет востребован метод сlеаг класса Роint.

1.11.2. Класс Object

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

Object objRef = new Piхед();

objRef = "Какая-то строка";

Пример демонстрирует, что переменная objRef способна содержать ссылки на объекты типов Piхеl и Stгing, хотя эти классы никак между собой не связаны, за исключением того, что оба неявным образом унаследованы от класса Object. В составе класса Object объявлено несколько весьма важных методов, более подробные сведения о которых приведены в главе 3.

1.11.3. Преобразованиl Типов

Следующий фрагмент Кода, на первый взгляд, вполне приемлем (хотя и не особенно полезен), но порождает ошибку компиляции:

String name = "Вася";

Object obj = name;

name = obj; // НЕВЕРНО: ошибка компиляции!

Мы объявляем и инициализируем ссылку на объект Stгing, присваиваем ее Переменной типа Object, а затем пытаемся выполнить обратное присваивание, чтобы вернуться к исходному положению вещей, сохранив в неприкосновенности дорогое сердцу имя. Что ж тут плохого? Проблема состоит в том, что хотя String – это всегда Object, Object, – это вовсе не обязательно String, и даже если в данном случае мы видим, что obj и в самом деле указывает на объект Stгing, компилятор не столь разумен и дальновиден. Чтобы помочь компилятору разобраться в ситуации, следует внятно подчеркнуть, что объект, адресуемый переменной obj, действительно относится к классу String и поэтому ссылку на него разрешается присвоить переменной name:

name = (String)obj; // вот так-то лучше!

Указывая компилятору на то, что выражение одного типа в действительности относится к другому типу, вы выполняете явное преобразование типов, предваряя выражение наименованием требуемого типа, заключенным в скобки. Примите к сведению, что и в этом случае компилятор не поверит вам на слово и все равно усомнится в том, говорите ли вы правду. Достаточно "образованный" компилятор может быть наделен способностью проверки правомочности предлагаемого вами преобразования еще на этапе компиляции; в противном случае он снабдит код дополнительными инструкциями, выявляющими возможность преобразования в момент выполнения про граммы. Если вы попытаетесь "обмануть" компилятор и инструкции про верки в период работы про граммы укажут на недопустимость преобразования, исполняющая система Java зарегистрирует этот факт и сгенерирует исключение типа ClassCastException. Java относится к разновидности строго типизированных языков программирования и поэтому устанавливает весьма жесткие правила в отношении возможности взаимного присваивания объектов различных типов.

Упражнение 1.13. Набросайте эскиз иерархии классов, отображающий зависимости между различными моделями компактных кассетных проигрывателей компании Sony, о которых мы говорили ранее. Обеспечьте сокрытие данных, объявив все поля классов как private, а методы как publiс. Какие методы следовало бы предусмотреть в базовом классе (назовем его Wa1kman), а какие целесообразно вынести в производные классы?

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии