Переопределение методов при наследовании — КиберПедия 

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Переопределение методов при наследовании

2019-08-04 193
Переопределение методов при наследовании 0.00 из 5.00 0 оценок
Заказать работу

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

Между переопределением и перегрузкой методов существует принципиальное различие. При перегрузке методы имеют одинаковые названия, но разные сигнатуры. При переопределении совпадают не только названия методов, но и полностью сигнатуры (тип результата, имя и список аргументов). Переопределение реализуется при наследовании. Для перегрузки в наследовании необходимости нет. Если наследуется перегруженный метод, то переопределение выполняется для каждой его версии в отдельности, причем переопределяются только те версии перегруженного метода, которые описаны в подклассе. Если в подклассе какая-то версия перегруженного метода не описана, эта версия наследуется из суперкласса.

Может сложиться и более хитрая ситуация. Допустим, в суперклассе определен некий метод, а в подклассе определяется метод с таким же именем, но другой сигнатурой. В этом случае в подклассе будут доступны обе версии метода: и исходная версия, описанная в суперклассе, и версия метода, описанная в подклассе.

То есть имеет место перегрузка метода, причем одна версия метода описана в суперклассе, а вторая — в подклассе.

В листинге 6 приведен пример программы с кодом переопределения метода.

Листинг 6. Переопределение метода

class ClassA{

static int count=0;

private int code;

int number;

ClassA(int n){

set(n);

count++;

code=count;

System.out.println("Объект №"+code+" создан!");}

void set(int n){

number=n;}

void show(){

System.out.println("Для объекта №"+code+":");

System.out.println("Поле number: "+number);}

}

class ClassB extends ClassA{

char symbol;

ClassB(int n,char s){

super(n);

symbol=s;}

void set(int n,char s){

number=n;

symbol=s;}

void show(){

super.show();

System.out.println("Поле symbol: "+symbol);}

}

class MyMethDemo{

public static void main(String[] args){

ClassA objA=new ClassA(10);

ClassB objB=new ClassB(-20,'a');

objA.show();

objB.show();

objB.set(100);

objB.show();

objB.set(0,'z');

objB.show();}

}

В результате выполнения программы получаем последовательность сообщений:

Объект №1 создан!

Объект №2 создан!

Для объекта №1:

Поле number: 10

Для объекта №2:

Поле number: -20

Поле symbol: a

Для объекта №2:

Поле number: 100

Поле symbol: a

Для объекта №2:

Поле number: 0

Поле symbol: z

Разберем программный код и результат его выполнения. В программе описывается класс ClassA (суперкласс), на основе которого создается подкласс ClassB.

Класс ClassA имеет целочисленное поле number, статическое целочисленное поле count (инициализированное нулевым значением) и закрытое целочисленное поле code. Кроме этого, в классе описан конструктор с одним аргументом (значением поля number), метод set() с одним аргументом для присваивания значения полю number, а также метод show() для отображения значения поля number.

Статическое поле count предназначено для учета количества созданных объектов.

При создании очередного объекта класса значение этого счетчика увеличивается на единицу. Для этого в конструкторе класса ClassA размещена команда count++.

Кроме этого в конструкторе с помощью метода set() присваивается значение полю number (в качестве аргумента методу передается аргумент конструктора), а командой code=count присваивается значение закрытому полю code. В поле code записывается порядковый номер, под которым создан соответствующий объект.

Поле count для этой цели не подходит, поскольку оно статическое и изменяется каждый раз при создании очередного объекта. В поле code записывается значение поля count после создания объекта и впоследствии поле code этого объекта не меняется.

Поле code (после присваивания значения полю) служит в конструкторе для вывода сообщения о создании объекта с соответствующим номером. Номер объекта (поле code) используется также в методе show(), чтобы легче было проследить, для какого именно объекта выводится информация о значении поля number.

Подкласс ClassB создается на основе суперкласса ClassA. В подклассе ClassB наследуется статическое поле count и поле number. Закрытое поле code не наследуется. Кроме этих наследуемых полей, непосредственно в классе ClassB описано символьное поле symbol. Конструктор класса принимает два аргумента: первый типа int для поля number и второй типа char для поля symbol.

Код конструктора класса ClassB состоит всего из двух команд: команды вызова конструктора суперкласса super(n) и команды присваивания значения символьному полю symbol=s (n и s — аргументы конструктора). Со второй командой все просто и понятно. Интерес представляет команда вызова конструктора суперкласса. Во-первых, этим конструктором наследуемому полю number присваивается значение. Во-вторых, значение наследуемого статического поля count увеличивается на единицу. Это означает, что ведется общий учет всех объектов, как суперкласса, так и подкласса. В-третьих, хотя поле code не наследуется, под него выделяется место в памяти и туда заносится порядковый номер созданного объекта. На экран выводится сообщение о создании нового объекта, а номер объекта считывается из «несуществующего» поля code.

Метод show() в классе ClassB переопределяется. Сигнатура описанного в классе ClassB метода show() совпадает с сигнатурой метода show(), описанного в классе ClassA. Если в классе ClassA методом show() отображается информация о номере объекта и значении его поля number, то в классе ClassB метод show() выводит еще и значение поля symbol. При этом в переопределенном методе show() вызывается также прежняя (исходная) версия метода из класса ClassA. Для этого используется инструкция вида super.show(). Этот исходный вариант метода, кроме прочего, считывает из ненаследуемого (но реально существующего) поля code порядковый номер объекта и отображает его в выводимом на экран сообщении.

Метод set() в классе ClassB перегружается. Хотя в классе ClassA есть метод с таким же названием, сигнатуры методов в суперклассе и подклассе разные.

В суперклассе у метода set() один числовой аргумент, а в подклассе у этого метода два аргумента: числовой и символьный. Поэтому в классе ClassB имеется два варианта метода set() — с одним и двумя аргументами. Первый наследуется из суперкласса ClassA, а второй определен непосредственно в подклассе ClassB.

В главном методе программы командами ClassA objA=new ClassA(10) и ClassB objB=new ClassB(-20,'a') создаются два объекта: объект objA суперкласса и объект objB подкласса. В результате выполнения этих команд на экране появляются сообщения Объект №1 создан! и Объект №2 создан! — сообщения выводятся конструкторами. Проверяются значения полей созданных объектов командами objA.show() и objB.show(). Поскольку метод show() перегружен, то в первом случае вызывается метод show(), описанный в суперклассе ClassA, а во втором — метод show(), описанный в подклассе ClassB. Поэтому для объекта objA выводится значение одного (и единственного) поля, а для объекта objB — значения двух полей.

Командой objB.set(100) метод set() вызывается из объекта objB. Поскольку в данном случае методу передан всего один аргумент, вызывается версия метода, описанная в классе ClassA. В результате меняется значение поля number объекта objB, а поле symbol остается неизменным. Подтверждается данное утверждение после вызова метода objB.show() (см. приведенный ранее результат выполнения программы). Если же воспользоваться командой objB.set(0,'z'), будет вызван тот вариант метода set(), который описан в классе ClassB. Выполнение команды objB.show() показывает, что в результате изменились оба поля объекта objB.

 

Многоуровневое наследование

Хотя множественное наследование (наследование сразу нескольких классов) в Java не допускается, с успехом может использоваться многоуровневое наследование. В этом случае подкласс становится суперклассом для другого подкласса.

Пример такой ситуации приведен в листинге 7.

Листинг 7. Многоуровневое наследование

class A{

int a;

A(int i){

a=i;

System.out.println("Поле a: "+a);}

}

class B extends A{

int b;

B(int i,int j){

super(i);

b=j;

System.out.println("Поле b: "+b);}

}

class C extends B{

int c;

C(int i,int j,int k){

super(i,j);

c=k;

System.out.println("Поле c: "+c);}

}

class MultiCall{

public static void main(String args[]){

C obj=new C(1,2,3);}

}

Ситуация достаточно простая: класс A является суперклассом для подкласса B. Класс B, в свою очередь, является суперклассом для подкласса C. Таким образом, получается своеобразная иерархия классов. В классе A всего одно числовое поле a и конструктор с одним аргументом. Аргумент определяет значение поля создаваемого объекта. Кроме того, при этом выводится сообщение о значении поля объекта.

В классе B наследуется поле a из класса A и появляется еще одно поле b. Соответственно, конструктор имеет два аргумента. Первый передается конструктору суперкласса (класс A), а второй определяет значение нового поля b. Также выводится сообщение о значении этого поля, однако прежде сообщение о значении поля a выводится конструктором суперкласса.

Два поля a и b наследуются в классе C. Там же описано числовое поле c. Первые два аргумента конструктора передаются конструктору суперкласса (класса B), а третий присваивается в качестве значения полю c. В конструкторе класса C имеется также команда вывода на экран значения этого поля. Значения полей a и b выводятся при выполнении конструктора суперкласса.

В главном методе программы командой C obj=new C(1,2,3) создается объект класса C. В результате на экране появляются сообщения:

Поле a: 1

Поле b: 2

Поле c: 3

Путем многоуровневого наследования можно создавать достаточно сложные иерархические структуры классов. Особенно механизм многоуровневого наследования становится эффективным при одновременном использовании механизмов перегрузки и переопределения методов. Пример простой, но показательной программы приведен в листинге 8.

Листинг 8. Многоуровневое наследование, перегрузка и переопределение методов

class A{

void show(){

System.out.println("Метод класса А");}

}

class B extends A{

void show(String msg){

System.out.println(msg);}

}

class C extends B{

void show(){

System.out.println("Метод класса C");}

}

class MultiOverride{

public static void main(String args[]){

A obj1=new A();

B obj2=new B();

C obj3=new C();

obj1.show();

obj2.show();

obj2.show("Класс В");

obj3.show();

obj3.show("Класс С");}

}

Как и в предыдущем примере, создается иерархическая цепочка из трех классов: в вершине находится суперкласс A, на основе которого создается подкласс B, в свою очередь являющийся суперклассом для подкласса C. При этом классами наследуется, перегружается или переопределяется описанный в классе A метод show(). Схему перегрузки и переопределения этого метода иллюстрирует рис. 1.

В частности, метод show() класса A не имеет аргументов и выводит сообщение Метод класса А. В классе B этот метод наследуется. Кроме того, в классе B метод show() перегружен с текстовым аргументом так, что он выводит сообщение, переданное в качестве его аргумента. Забегая наперед, отметим, что текстовый аргумент — это объект класса String. Текстовая строка, при передаче аргументом, заключается в двойные кавычки.

 


Рис. 1. Схема перегрузки и переопределения метода show() при многоуровневом наследовании

В классе C версия метода show() без аргумента переопределяется, а версия этого метода с текстовым аргументом наследуется из класса B.

В главном методе программы создаются три объекта — по объекту для каждого из классов. Затем из каждого объекта вызывается метод show() (с аргументами или без в зависимости от того, из какого объекта вызывается метод). В результате мы получаем следующее:

Метод класса А

Метод класса А

Класс В

Метод класса C

Класс С

Из объекта класса A вызывается версия метода без аргументов. Из объекта класса B метод вызывается без аргументов (версия метода из класса A) и с текстовым аргументом (версия метода, описанная в классе B). Вызываемая из объекта класса C версия метода без аргумента описана в классе C, а версия метода с текстовым аргументом наследуется из класса B.

 


Поделиться с друзьями:

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.039 с.