
- •Программирование на Java
- •Глава 1 Введение в java. Основы языка.
- •Тема 1.1 Язык программирования java.
- •Тема 1.2 Состав пакета Java2.
- •Тема 1.3 Настройка среды окружения.
- •Тема 1.4 Структура Java-программы.
- •Тема 1.5 Набор текста, запуск и компиляция простейшей программы.
- •Тема 1.6 Подробное рассмотрение кода простейшей программы.
- •Тема 1.7. Создание программы в разных средах разработки.
- •Тема 1.8 Лексические основы языка
- •Тема 1.9 Элементарные типы данных.
- •Тема 1.10 Преобразование типов.
- •Арифметические операции
- •Операции сравнения
- •Тема 1.11 Кoнсольный ввод с помощью класса java.Util.Scanner
- •Тема 1.12 Классы-оболочки
- •Тема 1.13 Автоупакока и автораспаковка.
- •Тема 1.14 Операторы
- •1.14.1 Блок
- •1.14.2 Условный оператор if
- •1.14.4 Оператор цикла while
- •1.14.5 Оператор цикла do-while
- •1.14.6 Оператор цикла for
- •1.14.7 Оператор continue и метки
- •1.14.8 Оператор break
- •1.14.9 Оператор варианта switch
- •Тема 1.15 Статический импорт
- •Тема 1.16 Класс Math
- •Задания
- •Тема 1.17 Псевдослучайные числа
- •Тема 1.18 Генерация случайных чисел
- •Тема 1.19 Массивы в Java
- •1.19.1 Объявление и заполнение массива
- •1.19.2 Сортировка массива
- •Сортировка выбором
- •Сортировка методом пузырька
- •1.19.3 Многомерные массивы
- •Задания
- •1.19.4 Нерегулярные массивы
- •Глава 2 классы
- •Тема 2.1 Основы классов
- •Тема 2.2 Общая форма класса
- •Тема 2.3 Объявление объектов
- •Тема 2.4 Более подробное рассмотрение операции new
- •Тема 2.5 Присваивание переменных объектных ссылок
- •Тема 2.6 Знакомство с методами
- •Тема 2.7 Возвращение значения из метода
- •Тема 2.8 Добавление метода, принимающего параметры
- •Тема 2.9 Конструкторы
- •Тема 2.10 Сборка мусора
- •Тема 2.11 Перегрузка методов
- •Тема 2.12 Перегрузка конструкторов
- •Тема 2.13 Использование объектов в качестве параметров
- •Тема 2.14 Более пристальный взгляд на передачу аргументов
- •Тема 2.16 Рекурсия
- •Тема 2.17 Введение в управление доступом
- •Тема 2.18 Ключевое слово static
- •Тема 2.19 Ключевое слово final
- •Тема 2.20 Аргументы переменной длины
- •Тема 2.21 Строки и числа
- •Тема 2.22 Нумерованные типы
- •Глава 3 наследование и интерфейсы
- •Тема 3.1 Основы наследования
- •Тема 3.2 Наследование и доступ к членам класса
- •Тема 3.3 Конструкторы и наследование
- •Тема 3.4 Использование ключевого слова super для вызова конструктора суперкласса
- •Тема 3.5 Использование ключевого слова super для доступа к членам суперкласса
- •Тема 3.6 Многоуровневая иерархия
- •Тема 3.7 Когда вызываются конструкторы
- •Тема 3.8 Объекты подклассов и ссылки на суперклассы
- •Тема 3.9 Переопределение методов
- •Тема 3.10 Переопределение методов и поддержка полиморфизма
- •Тема 3.11 Использование абстрактных классов
- •Тема 3.12 Использование ключевого слова final
- •Тема 3.13 Предотвращение переопределения методов
- •Тема 3.14 Предотвращение наследования
- •Тема 3.15 Класс Object
- •Тема 3.16 Интерфейсы
- •3.16.1 Объявление интерфейса.
- •3.16.2 Реализация интерфейсов
- •3.16.3 Использование ссылок на интерфейсы
- •3.16.4 Переменные в составе интерфейсов
- •3.16.5 Наследование интерфейсов
- •Тема 3.17 Пакеты и ограничение доступа
- •Тема 3.18 Внутренние классы
- •3.18.1 Внутренние (inner) классы
- •3.18.2 Вложенные (nested) классы
- •3.18.3 Анонимные (anonymous) классы
- •Глава 4 Обработка исключительных ситуаций
- •Тема 4.1 Исключения в Java
- •Тема 4.2 Типы исключений
- •Тема 4.3 Неперехваченные исключения
- •Тема 4.4 Ключевые слова try и catch
- •Тема 4.6 Ключевое слово throw
- •Тема 4.7 Ключевое слово throws
- •Тема 4.8 Ключевое слово finally
- •Ошибка при выполнении метода1 java.Lang.ArithmeticException: Demo
- •Тема 4.9 Потомки Exception или написание своих классов ошибок
- •Глава 5 Универсальные типы. КоллекциИ
- •Тема 5.1 Общие сведения об универсальных типах
- •Тема 5.2 Универсальный класс с двумя параметрами типа
- •Тема 5.3 Ограниченные типы
- •Тема 5.4 Использование групповых параметров
- •Тема 5.5 Универсальные методы
- •Тема 5.6 Универсальные интерфейсы
- •Тема 5.7 Ошибки неоднозначности
- •Тема 5.8 Ограничения универсальных типов
- •Тема 5.9 Краткий обзор коллекций
- •5.9.1 Класс ArrayList
- •5.9.2 Класс LinkedList
- •5.9.3 Класс HashSet
- •5.9.4 Класс TreeSet
- •5.9.5 Доступ к коллекции через итератор
- •5.9.6 Алгоритмы коллекций
- •Глава 6 jdbc (Java DataBase Connectivity) Тема 6.1 Драйверы, соединения и запросы
- •Тема 6.2 Простое соединение и простой запрос
- •Тема 6.2 Класс ResultSet
- •Тема 6.3 Метаданные
- •Тема 6.4 Подготовленные запросы
- •Глава 7 Swing и пользовательский интерфейс
- •Тема 7.1 Общие сведения о swing
- •Тема 7.2 Архитектура mvc
- •Тема 7.3 Контейнер и компоненты
- •Тема 7.4 Простая программа, использующая средства Swing
- •Тема 7.5 Поддержка событий
- •Тема 7.6 Использование кнопок и обработка событий
- •Тема 7.7 Краткие сведения о диспетчерах компоновки
- •Тема 7.8 Пример использования jdbc и swing вместе
Тема 3.11 Использование абстрактных классов
В некоторых случаях необходимо создать суперкласс, который лишь определяет общий формат, детали же уточняются лишь в его подклассах. В таком суперклассе нет необходимости реализовывать методы, – эта задача делегируй дочерним классам. Иногда подобная потребность возникает потому, что в суперклассе попросту невозможно создать осмысленную реализацию метода. Таким является класс TwoDShape, рассмотренный в предыдущих примерах. В нем метод area() представляет собой не более чем заглушку. Он не способен вычислить и отобразить площадь конкретного объекта.
Когда вы начнете создавать свои библиотеки классов, то увидите, что ситуация, при которой в контексте суперкласса невозможно реализовать тот или иной метод, встречается очень часто. Справиться с такой проблемой можно двумя способами. Один из них был рассмотрен в предыдущем примере. Он состоит в том что метод лишь отображает предупреждающее сообщение. Такой подход может быть полезным в ряде случаев, например при отладке, но в большинстве ситуаций он совершенно неприменим. Поэтому чаще всего применяется второй способ, позволяющий создать метод, который должен быть переопределен в подклассе там, где он приобретает конкретный смысл. Рассмотрим класс Triangle. Он будет неполон, если не определить метод area(). Нужен механизм, позволяющий убедиться в том, что в подклассе переопределены требуемые методы. В языке Java этот механизм носит название абстрактный метод.
При создании абстрактного метода используется модификатор abstract. Тело абстрактного метода отсутствует, поэтому он не реализуется в суперклассе. В подклассе он должен быть переопределен. Использовать вариант метода, объявленный в суперклассе, невозможно. Абстрактный метод объявляется в следующем формате:
abstract тип имя (список_параметров);
Как видите, тело метода отсутствует. Модификатор abstract применим только с обычными методами. Он не может быть использован со статическими методами или с конструкторами.
Класс, содержащий хотя бы один абстрактный метод, также должен быть объявлен абстрактным, т.е. в определении класса должен присутствовать спецификатор abstract. Поскольку в абстрактном классе отсутствует определение хотя бы одного метода, экземпляр такого класса создать невозможно. Попытка сформировать соответствующий объект посредством оператора new приведет к возникновению ошибки на этапе компиляции.
Подкласс, наследующий абстрактный класс, должен реализовать все абстрактные методы. Если это не будет сделано, то подкласс также должен быть абстрактным. Таким образом, подклассы останутся абстрактными до тех пор, пока все абстрактные методы не будут реализованы. Теперь мы можем модифицировать класс TwoDShape, используя модификатор abstract. Поскольку говорить о площади фигуры невозможно до тех пор, пока тип фигуры не будет конкретизирован, в классе TwoDShape есть смысл добавить абстрактный метод area(), а в определении самого класса также использовать модификатор abstract. Это будет означать, что во всех подклассах класса TwoDShape должен быть переопределен метод area().
Листинг 3.19
// Создание абстрактного класса
public abstract class TwoDShape {
private double width;
private double height;
private String name;
// Конструктор по умолчанию
public TwoDShape() {
width = height = 0.0;
name = "null";
}
// Конструктор с параметрами
public TwoDShape(double w, double h, String n) {
width = w;
height = h;
name = n;
}
// Формирование объекта с одинаковыми значениями width и height
public TwoDShape(double x, String n) {
width = height = x;
name = n;
}
// Формирование объекта на основе другого объекта
public TwoDShape(TwoDShape ob) {
width = ob.width;
height = ob.height;
name = ob.name;
}
// Методы для доступа к переменным width и height
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public void setWidth(double w) {
width = w;
}
public void setHeight(double h) {
height = h;
}
public String getName() {
return name;
}
public void showDim() {
System.out.println("Width and height are "
+ width + " and " + height);
}
// Теперь метод area() абстрактный
public abstract double area();
}
// Подкласс класса TwoDShape для представления треугольников
public class Triangle extends TwoDShape {
private String style;
// Конструктор по умолчанию
public Triangle() {
super();
style = "null";
}
// Конструктор класса Triangle
public Triangle(String s, double w, double h) {
super(w, h, "triangle");
style = s;
}
// Формирование равнобедренного треугольника
public Triangle(double x) {
super(x, "triangle"); // Вызов конструктора суперкласса
style = "isosceles";
}
// Формирование объекта на основе другого объекта
public Triangle(Triangle ob) {
super(ob); // Передача объекта конструктору TwoDShape
style = ob.style;
}
public double area() {
return getWidth() * getHeight() / 2;
}
public void showStyle() {
System.out.println("Triangle is " + style);
}
}
// Подкласс класса TwoDShape для представления прямоугольников
public class Rectangle extends TwoDShape {
// Конструктор по умолчанию
public Rectangle() {
super();
}
// Конструктор класса Rectangle
public Rectangle(double w, double h) {
super(w, h, "rectangle"); // Вызов конструктора суперкласса
}
// Формирование квадрата
public Rectangle(double x) {
super(x, "rectangle"); // Вызов конструктора суперкласса
}
// Формирование объекта на основе другого объекта
public Rectangle(Rectangle ob) {
super(ob); // Передача объекта конструктору TwoDShape
}
public boolean isSquare() {
if (getWidth() == getHeight()) {
return true;
}
return false;
}
public double area() {
return getWidth() * getHeight();
}
}
public 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() сокращено до четырех; объект TwoDShape теперь не создается.
И еще одно замечание. Обратите внимание на то, что в классе TwoDShape по-прежнему присутствуют определения методов showDim () и getName () и перед ними нет модификатора abstract. Это допустимо; абстрактный класс имеет право содержать полностью определенные методы, которые могут быть или не быть переопределены в подклассах. Обязательному переопределению подлежат лишь те методы, перед которыми указан модификатор abstract.
Задание:
Напишите класс Собака, который наследуется от класса Животные. В классы Собака и Кот добавьте метод голос. В классе Животные этот метод абстрактный.