Ильдар Хабибуллин - Java 7 [Наиболее полное руководство]
- Название:Java 7 [Наиболее полное руководство]
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2012
- ISBN:978-5-9775-0735-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Ильдар Хабибуллин - Java 7 [Наиболее полное руководство] краткое содержание
Java 7 [Наиболее полное руководство] - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Зачем же нужны абстрактные классы? Не лучше ли сразу написать необходимые классы с полностью определенными методами, а не наследовать их от абстрактного класса? Для ответа снова обратимся к листингу 2.2.
Хотя элементы массива singer[] ссылаются на подклассы Dog, Cat, Cow, но все-таки это переменные типа Pet и ссылаться они могут только на поля и методы, описанные в суперклассе Pet. Дополнительные поля подкласса для них недоступны. Попробуйте обратиться, например, к полю k класса Dog, написав singer[0] .k. Компилятор "скажет", что он не может найти такое поле. Поэтому метод, который реализуется в нескольких подклассах, приходится выносить в суперкласс, а если там его нельзя реализовать, то объявить абстрактным. Таким образом, абстрактные классы группируются на вершине иерархии классов.
Кстати, можно задать пустую реализацию метода, просто поставив пару фигурных скобок, ничего не написав между ними, например:
void voice(){}
Получится полноценный метод, хотя он ничего не делает. Но это искусственное решение, запутывающее структуру класса.
Замкнуть же иерархию можно окончательными классами.
Окончательные члены и классы
Пометив метод модификатором final, можно запретить его переопределение в подклассах. Это удобно в целях безопасности. Вы можете быть уверены, что метод выполняет те действия, которые вы задали. Именно так определены математические функции sin ( ), cos ( ) и пр. в классе Math. Мы уверены, что метод Math.cos(x) вычисляет именно косинус числа х. Разумеется, такой метод не может быть абстрактным.
Для полной безопасности поля, обрабатываемые окончательными методами, следует сделать закрытыми (private).
Если пометить модификатором final параметр метода, то его нельзя будет изменить внутри метода.
Если же пометить модификатором final весь класс, то его вообще нельзя будет расширить. Так определен, например, класс Math:
public final class Math{ . . . }
Для переменных модификатор final имеет совершенно другой смысл. Если пометить модификатором final описание переменной, то ее значение (а оно должно быть обязательно задано или здесь же, или в блоке инициализации, или в конструкторе) нельзя изменить ни в подклассах, ни в самом классе. Переменная превращается в константу. Именно так в языке Java определяются константы:
public final int MIN_VALUE = -1, MAX_VALUE = 9999;
По соглашению "Code Conventions" константы записываются прописными буквами, слова в них разделяются знаком подчеркивания.
Класс Object
На самой вершине иерархии классов Java стоит класс Object.
Если при описании класса мы не указываем никакое расширение, т. е. не пишем слово extends и имя класса за ним, как при описании класса Pet, то Java считает этот класс расширением класса Object, и компилятор дописывает это за нас:
class Pet extends Object{ . . . }
Можно записать это расширение и явно.
Сам же класс Obj ect не является ничьим наследником, от него начинается иерархия любых классов Java. В частности, все массивы — прямые наследники класса Object.
Поскольку такой класс может содержать только общие свойства всех классов, в него включено лишь несколько самых общих методов, например метод equals(), сравнивающий данный объект на равенство с объектом, заданным в аргументе, и возвращающий логическое значение. Его можно использовать так:
Object objl = new Dog(), obj2 = new Cat(); if (obj1.equals(obj2)) ...
Оцените объектно-ориентированный дух этой записи: объект obj 1 активен, он сам сравнивает себя с другим объектом. Можно, конечно, записать и obj2.equals(obji), сделав активным объект obj 2, с тем же результатом.
Как указывалось в главе 1, ссылки можно сравнивать на равенство и неравенство:
obj 1 == obj 2; obj 1 ! = obj 2;
В этом случае сопоставляются адреса объектов, мы можем узнать, не указывают ли обе ссылки на один и тот же объект.
Метод equals () же сравнивает содержимое объектов в их текущем состоянии, фактически он реализован в классе Object как тождество: объект равен только самому себе. Поэтому его обычно переопределяют в подклассах; более того, правильно спроектированные, "хорошо воспитанные" классы должны переопределить методы класса Obj ect, если их не устраивает стандартная реализация. Например, в классе String метод equals () сравнивает не адреса размещения строк в оперативной памяти, а символы, из которых состоит строка, как мы увидим в главе 5.
Второй метод класса Object, часто требующий переопределения,- метод hashCode( ) —
возвращает целое число, уникальное для каждого объекта данного класса, его идентификатор. Это число позволяет однозначно определить объект. Оно используется многими стандартными классами Java. Реализация метода hashCode (), сделанная в классе Obj ect, может оказаться недостаточной для какого-то подкласса. В таком случае метод hashCode () следует переопределить.
Третий метод класса Object, который следует переопределять в подклассах, — метод tostring (). Это метод без параметров, который выражает содержимое объекта строкой символов и возвращает объект класса string. В классе Object метод tostring() реализован очень скудно — он выдает имя класса и идентификатор объекта, возвращаемый методом hashCode (). Метод tostring() важен потому, что исполняющая система Java обращается к нему каждый раз, когда требуется представить объект в виде строки, например в методе println(). Обычно метод tostring() переопределяют так, чтобы он возвращал информацию о классе объекта и текущие значения его полей, записанные в виде строк символов.
Конструкторы класса
Вы уже обратили внимание на то, что в операции new, определяющей экземпляры класса, повторяется имя класса со скобками. Это похоже на обращение к методу, но что за "метод", имя которого полностью совпадает с именем класса?
Такой "метод" называется конструктором класса (class constructor). Его задача — определение полей создаваемого объекта начальными значениями. Своеобразие конструктора заключается не только в имени. Перечислим особенности конструктора.
□ Конструктор имеется в любом классе. Даже если вы его не написали, компилятор Java сам создаст конструктор по умолчанию (default constructor), который, впрочем, пуст, он не делает ничего, кроме вызова аналогичного конструктора по умолчанию суперкласса.
□ Конструктор выполняется автоматически при создании экземпляра класса, после распределения памяти и инициализации полей, но до начала использования создаваемого объекта.
□ Конструктор не возвращает никакого значения. Поэтому в его описании не пишется даже слово void, но можно задать один из трех модификаторов: public, protected или
private.
□ Конструктор не является методом, он даже не считается членом класса. Поэтому его нельзя наследовать или переопределить в подклассе.
□ Тело конструктора может начинаться:
• с вызова одного из конструкторов суперкласса, для этого записывается слово super () с параметрами конструктора суперкласса в скобках, если они нужны;
Читать дальшеИнтервал:
Закладка: