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

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

Жанры

Java: руководство для начинающих
Шрифт:

Ниже приведен результат выполнения данной программы. object is triangle Area is 48.0 object is rectangle Area is 100.0 object is rectangle Area is 40.0 object is triangle Area is 24.5 object is generic area must be overridden Area is 0.0

Рассмотрим код данной программы более подробно. Теперь, как и предполагалось при написании программы, метод area входит в состав класса TwoDShape и переопределяется в классах Triangle и Rectangle. В классе TwoDShape метод area играет роль заполнителя и лишь уведомляет пользователя о том, что этот метод должен быть переопределен в подклассе. При каждом переопределении метода area в нем реализуются средства, необходимые для того типа объекта, который инкапсулируется в подклассе. Так, если требуется реализовать класс для эллипсов, метод area придется переопределить таким образом, чтобы он вычислял площадь этой фигуры.

У рассматриваемой здесь программы имеется еще одна важная особенность. Обратите внимание на то,

что в методе main геометрические фигуры объявляются как массив объектов типа TwoDShape. Но на самом деле элементами массива являются ссылки на объекты Triangle, Rectangle и TwoDShape. Это вполне допустимо. Ведь, как пояснялось ранее, переменная ссылки на суперкласс может ссылаться на объект его подкласса. В этой программе организован перебор элементов массива в цикле и вывод сведений о каждом объекте. Несмотря на всю простоту данного примера, он наглядно демонстрирует потенциальные возможности как наследования, так и переопределения методов. Тип объекта, на который указывает переменная ссылки на суперкласс, определяется на этапе выполнения программы и обрабатывается соответствующим образом. Если объект является производным от класса TwoDShape, его площадь вычисляется при вызове метода area . Интерфейс для данной операции оказывается общим и не зависит от того, с какой именно геометрической фигурой приходится иметь дело каждый раз. Применение абстрактных классов

Иногда требуется создать суперкласс, в котором определяется лишь самая общая форма для всех его подклассов, а наполнение ее деталями предоставляется каждому из этих подклассов. В таком классе определяется лишь характер методов, которые должны быть конкретно реализованы в подклассах, а не в самом суперклассе. Подобная ситуация возникает, например, в связи с невозможностью получить содержательную реализацию метода в суперклассе. Именно такая ситуация была продемонстрирована в варианте класса TwoDShape из предыдущего примера, где метод area был просто определен как заполнитель. Такой метод не вычисляет и не выводит площадь двумерной геометрической формы любого типа.

Создавая собственные библиотеки классов, вы можете сами убедиться в том, что у метода зачастую отсутствует содержательное определение в контексте его суперкласса. Подобное затруднение разрешается двумя способами. Один из них, как показано в предыдущем примере, состоит в том, чтобы просто выдать предупреждающее сообщение. И хотя такой способ может пригодиться в некоторых случаях, например при отладке, в практике программирования он обычно не применяется. Ведь в суперклассе могут быть объявлены методы, которые должны быть переопределены в подклассе, чтобы этот класс стал содержательным. Рассмотрим для примера класс Triangle. Он был бы неполным, если бы в нем не был переопределен метод area . В подобных случаях требуется какой-то способ, гарантирующий, что в подклассе действительно будут переопределены все необходимые методы. И такой способ в Java имеется. Он состоит в использовании абстрактного метода.

Абстрактный метод создается с помощью указываемого модификатора типа abstract. У абстрактного метода отсутствует тело, и поэтому он не реализуется в суперклассе. Это означает, что он должен быть переопределен в подклассе, поскольку его вариант из суперкласса просто непригоден для использования. Для определения абстрактного метода служит приведенная ниже общая форма, abstract тип имя (список_параметров);

Как видите, у абстрактного метода отсутствует тело. Модификатор abstract может применяться только к обычным методам, но не к статическим методам (static) и конструкторам.

Класс, содержащий один или более абстрактный метод, должен быть также объявлен как абстрактный, для чего перед его объявлением class указывается модификатор abstract. А поскольку реализация абстрактного класса не определяется полностью, то у него не может быть объектов. Следовательно, попытка создать объект абстрактного класса с помощью оператора new приведет к ошибке во время компиляции.

Когда подкласс наследует абстрактный класс, в нем должны быть реализованы все абстрактные методы суперкласса. В противном случае подкласс должен быть также определен как abstract. Таким образом, атрибут abstract наследуется до тех пор, пока не будет достигнута полная реализация класса.

Используя абстрактный класс, мы можем усовершенствовать рассматривавшийся ранее класс TwoDShape-Для неопределенной двумерной геометрической фигуры понятие площади не имеет никакого смысла, поэтому в приведенной ниже версии предыдущей программы метод area и сам класс TwoDShape объявляются как abstract. Это, конечно, означает, что во всех классах, производных от класса TwoDShape, должен быть переопределен метод area . // Создание абстрактного класса. // Теперь класс TwoDShape является абстрактным. abstract class TwoDShape { private double width; private double height; private String name; // Конструктор no умолчанию. TwoDShape { width = height = 0.0; name = "null"; } // Параметризированный конструктор. TwoDShape(double w, double h, String n) { width = w; height = h; name = n; } //

построить объект с одинаковыми значениями // переменных экземпляра width и height TwoDShape(double х, String n) { width = height = x; name = n; } // построить один объект на основании другого объекта TwoDShape(TwoDShape ob) { width = ob.width; height = ob.height; name = ob.name; } // Методы доступа к переменным width и height, double getWidth { return width; } double getHeightO { return height; } void setWidth(double w) { width = w; } void setHeight(double h) { height = h; } String getName { return name; } void showDim { System.out.println("Width and height are " + width + " and " + height); } // Теперь метод area является абстрактным. abstract double area; } // Подкласс, производный от класса TwoDShape, // для представления треугольников, class Triangle extends TwoDShape { private String style; // Конструктор по умолчанию. Triangle { super ; style = "null"; } // Конструктор класса Triangle. Triangle(String s, double w, double h) { super(w, h, "triangle"); style = s; } // Конструктор с одним аргументом для построения треугольника. Triangle(double х) { super(х, "triangle"); // вызвать конструктор суперкласса style = "isosceles"; } // построить один объект на основании другого объекта Triangle(Triangle ob) { super(ob); // передать объект конструктору класса TwoDShape style = ob.style; } double area { return getWidth * getHeight / 2; } void showStyle { System.out.println("Triangle is " + style); } } // Подкласс, производный от класса TwoDShape, // для представления прямоугольников. class Rectangle extends TwoDShape { // Конструктор по умолчанию. Rectangle { super; } // Конструктор класса Rectangle. Rectangle(double w, double h) { super(w, h, "rectangle"); // вызвать конструктор суперкласса } // построить квадрат Rectangle(double х) { super(х, "rectangle"); // вызвать конструктор суперкласса } // построить один объект на основании другого объекта Rectangle(Rectangle ob) { super(ob); // передать объект конструктору класса TwoDShape } boolean isSquare { if (getWidth == getHeightO) return true; return false; } double area { return getWidth * getHeightO; } } class AbsShape { public static void main(String args[]) { TwoDShape shapes[] = new TwoDShape[4]; shapes[0] = new Triangle("right", 8.0, 12.0); shapes[1] = new Rectangle(10); shapes[2] = new Rectangle(10, 4); shapes[3] = new Triangle(7.0); for(int i=0; i < shapes.length; i++) { System.out.println("object is " + shapes[i].getName); System.out.println("Area is " + shapes[i].area); System.out.println; } } }

Как показывает представленный выше пример программы, во всех подклассах, производных от класса TwoDShape, метод area должен быть непременно переопределен. Убедитесь в этом сами, попробовав создать подкласс, в котором не переопределен метод area . В итоге вы получите сообщение об ошибке во время компиляции. Конечно, возможность создавать ссылки на объекты типа TwoDShape по-прежнему существует, и это было сделано в приведенном выше примере программы, но объявлять объекты типа TwoDShape уже нельзя. Именно поэтому массив shapes сокращен в методе main до 4 элементов, а объект типа TwoDShape для общей двумерной геометрической формы больше не создается.

И еще одно, последнее замечание. Обратите внимание на то, что в классе TwoDShape по-прежнему присутствуют определения методов showDim и getName и перед их именами нет модификатора abstract. В абстрактные классы вполне допускается (и часто практикуется) включать конкретные методы, которые могут быть использованы в своем исходном виде в подклассе. А переопределению в подклассах подлежат только те методы, которые объявлены как abstract. Использование ключевого слова final

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

Для того чтобы предотвратить переопределение метода, в начале его объявления нужно указать модификатор доступа final. Переопределять объявленные подобным образом методы нельзя. Ниже приведен фрагмент кода, демонстрирующий использование ключевого слова final для подобных целей. class А { final void meth { System.out.println("This is a final method."); } } class В extends А { void meth { // Ошибка! Переопределить метод нельзя. System.out.println("Illegal!") ; } }

Поскольку метод meth объявлен как final, его нельзя переопределить в классе В. Если вы попытаетесь сделать это, возникнет ошибка при компиляции программы. Предотвращение наследования

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

Измена. (Не)любимая жена олигарха

Лаванда Марго
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха

Хозяйка дома в «Гиблых Пределах»

Нова Юлия
Любовные романы:
любовно-фантастические романы
5.75
рейтинг книги
Хозяйка дома в «Гиблых Пределах»

Фиктивный брак

Завгородняя Анна Александровна
Фантастика:
фэнтези
6.71
рейтинг книги
Фиктивный брак

На границе империй. Том 7. Часть 2

INDIGO
8. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
6.13
рейтинг книги
На границе империй. Том 7. Часть 2

Держать удар

Иванов Дмитрий
11. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Держать удар

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Драконий подарок

Суббота Светлана
1. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
7.30
рейтинг книги
Драконий подарок

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

По дороге на Оюту

Лунёва Мария
Фантастика:
космическая фантастика
8.67
рейтинг книги
По дороге на Оюту

Мастер 5

Чащин Валерий
5. Мастер
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Мастер 5

Не лечи мне мозги, МАГ!

Ордина Ирина
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.00
рейтинг книги
Не лечи мне мозги, МАГ!

Измена. Право на семью

Арская Арина
Любовные романы:
современные любовные романы
5.20
рейтинг книги
Измена. Право на семью

Крепость над бездной

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

Неудержимый. Книга XXI

Боярский Андрей
21. Неудержимый
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Неудержимый. Книга XXI