Помощничек
Главная | Обратная связь


Археология
Архитектура
Астрономия
Аудит
Биология
Ботаника
Бухгалтерский учёт
Войное дело
Генетика
География
Геология
Дизайн
Искусство
История
Кино
Кулинария
Культура
Литература
Математика
Медицина
Металлургия
Мифология
Музыка
Психология
Религия
Спорт
Строительство
Техника
Транспорт
Туризм
Усадьба
Физика
Фотография
Химия
Экология
Электричество
Электроника
Энергетика

Концепция наследования



Наследование – один из краеугольных камней объектно-ориентированного программирования, потому что оно позволяет создавать иерархические классификации. Используя наследование, можно создать главный класс, который определяет свойства, общие для набора связанных элементов. Затем этот класс может быть унаследован другими, более специфическими классами, каждый из которых добавляет те свойства, которые являются уникальными для него. В терминологии Java класс, который унаследован, называется суперклассом (superclass). Класс, который выполняет наследование, называется подклассом (subclass). Поэтому подкласс – это специализированная версия суперкласса. Он наследует все переменные экземпляра и методы, определенные суперклассом, и прибавляет свои собственные уникальные элементы.

Наследование (inheritance) – это отношение между классами, при котором класс использует структуру или поведение другого класса (одиночное наследование), или других (множественное наследование) классов. Наследование вводит иерархию «общее/частное», в которой подкласс наследует от одного или нескольких более общих суперклассов. Подклассы обычно дополняют или переопределяют унаследованную структуру и поведение.

В качестве примера можно рассмотреть задачу, в которой необходимо реализовать классы «Легковой автомобиль» и «Грузовой автомобиль». Очевидно, эти два класса имеют общую функциональность. Так, оба они имеют 4 колеса, двигатель, могут перемещаться и т.д. Всеми этими свойствами обладает любой автомобиль, независимо от того, грузовой он или легковой, 5- или 12-местный. Разумно вынести эти общие свойства и функциональность в отдельный класс, например, «Автомобиль» и наследовать от него классы «Легковой автомобиль» и «Грузовой автомобиль», чтобы избежать повторного написания одного и того же кода в разных классах.

 

Рисунок 1. Пример наследования автомобилей

 

Отношение обобщения обозначается сплошной линией со стрелкой на конце. Стрелка указывает на более общий класс (класс-предок или суперкласс), а ее отсутствие – на более специальный класс (класс-потомок или подкласс).

Использование наследования способствует уменьшению количества кода, созданного для описания схожих сущностей, а также способствует написанию более эффективного и гибкого кода.

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

Все животные в зоомагазине являются наследниками класса «Животное», а также наследниками класса «Товар». Т.е. все они имеют возраст, нуждаются в пище и воде и в то же время имеют цену и могут быть проданы.

Множественное наследование на диаграмме изображается точно так же, как одиночное, за исключением того, что линии наследования соединяют класс-потомок сразу с несколькими суперклассами.

Не все объектно-ориентированные языки программирования содержат языковые конструкции для описания множественного наследования.

В языке Java множественное наследование имеет ограниченную поддержку через интерфейсы.

Перегрузка методов

В языке Java в пределах одного класса можно определить два или более методов, которые совместно используют одно и то же имя, но имеют разное количество параметров. Когда это имеет место, методы называют перегруженными, а о процессе говорят как о перегрузке метода. Чтобы определить, какую версию перегруженного метода в действительности вызывать, Java руководствуется типом и/или числом его параметров. Таким образом, перегруженные методы должны отличаться по типу и/или числу их параметров. Хотя такие методы могут иметь различные типы возвращаемого значения, однако одного eгo недостаточно, чтобы различить две версии метода. Когда Java сталкивается с вызовом перегруженного метода, он просто выполняет ту версию, чьи параметры соответствуют параметрам, используемым в вызове.

 

// Простой пример, который иллюстрирует перегруженный метод:

// Демонстрация перегруженного метода

class OverloadDemo {

void test() {

System.out.println("Параметры отсутствуют");

}

// Перегруженный метод test с одним int-параметром.

void test(int a) {

System.out.println("a: " + a);

}

// Перегруженный метод test с двумя int-параметрами.

void test(int a, int b) {

System.out.println("а и b: " + a + " " + b);

}

// Перегруженный метод test с double-параметром.

double test(double a) {

System.out.println("Вещественное двойной точности a: " + a);

return a*a;

}

}

 

class Overload {

public static void main(String args[]) {

OverloadDemo ob = new OverloadDemo();

double result;

 

// вызвать все версии test()

ob.test ();

ob.test(10);

ob.test(10, 20);

result = ob.test(123.2);

System.out.println("Результат ob.test(123.2): " + result);

}

}

 

Эта программа генерирует следующий вывод:

 

Параметры отсутствуют

a: 10

а и b: 10 20

Вещественное двойной точности a: 123.2

Результат ob.test(123.2): 15178.240000000002

 

Метод test() перегружен четыре раза. Первая версия не имеет никаких параметров, вторая имеет один параметр целого типа, третья — два целочисленных параметра, а четвертая — один double-параметр. Тот факт, что четвертая версия test() еще и возвращает значение, не имеет никакого отношения к перегрузке, так как типы возвращаемых значений не играют никакой роли для выбора перегруженных методов.

Когда вызывается перегруженный метод, Java ищет соответствие между аргументами вызова метода и его параметрами. Однако это соответствие не всегда может быть точным. В некоторых случаях определенную роль в выборе перегруженного метода могут сыграть автоматические преобразования типов Java. Например, рассмотрим следующую программу:

 

// Автоматическое преобразование типов в применении к перегрузке.

class OverloadDemo {

void test() {

System.out.println("Параметры отсутствуют");

}

// Перегруженный test с двумя int-параметрами.

void test(int a, int b) {

System.out.println("а и b: " + a + " " + b);

}

// Перегруженный test с double-параметром и возвращаемым типом.

void test(double a) {

System.out.println("Внутри test(double) a: " + a);

}

}

 

class Overload2 {

public static void main(String args[]) {

OverloadDemo ob = new OverloadDemo();

int i = 88;

 

ob.test () ;

ob.test(10, 20);

ob.test(i); // здесь будет вызван test(double)

ob.test(123.2); // здесь будет вызван test(double)

}

}

 

Эта программа генерирует следующий вывод:

 

Параметры отсутствуют

а и b: 10 20

Внутри test(double) a: 88.0

Внутри test(double) a: 123.2

 

Эта версия OverloadDemo не определяет test(int) с одним целым параметром. Поэтому, когда test() вызывается с целым аргументом внутри класса overload2, никакого согласованного метода не находится. Однако Java может автоматически преобразовывать int в double, и это преобразование можно использовать для разрешения вызова. Поэтому, после того, как test (int) не находится, Java расширяет i до double и затем вызывает test(double). Конечно, если бы test(int) был определен, то он вызывался бы вместо test(double). Java использует эти автоматические преобразования типов только тогда, когда никакого точного соответствия не находится.

Когда вы перегружаете метод, каждая версия этого метода может выполнять любое действие, какое вы пожелаете. Нет никакого правила, заявляющего, как перегруженные методы должны быть связаны друг с другом. Однако, со стилистической точки зрения, перегрузка метода подразумевает некоторую их взаимосвязь. Таким образом, хотя можно использовать то же самое имя чтобы перезагрузить несвязанные методы, но этого делать не нужно. Например, можно использовать имя sqr, чтобы создать методы, возвращающие квадрат целого числа и квадратный корень числа с плавающей точкой. Но эти две операции совершенно различны. Такой способ применения перегрузки метода противоречит его первоначачьной цели. Практически, следует перегружать только тесно связанные операции.

 




Поиск по сайту:

©2015-2020 studopedya.ru Все права принадлежат авторам размещенных материалов.