Spiral group

_________________________________________________________________________________

 

< Раздел “Язык Java > < Раздел “Технологии Java > < Основная страница >

 

Полиморфизм в Java

 

Статья опубликована: 19.04.2006

 

 

Полиморфизм (от греч. – “имеющий много форм”).

 

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

 

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

 

Полиморфизм при помощи абстрактных классов. Абстрактные классы поддерживают как наследование, так и возможности интерфейсов. При построении сложной иерархии, для обеспечения полиморфизма программисты часто вынуждены вводить методы в классы верхнего уровня при том, что эти методы ещё не определены. Абстрактный класс – это класс, экземпляр которого невозможно создать; этот класс может лишь служить базовым классом при наследовании. Нельзя объявлять абстрактные конструкторы или абстрактные статические методы. Некоторые или все члены этого класса могут оставаться нереализованными, их реализацию должен обеспечить наследующий класс. Производные классы, которые не переопределяют все абстрактные методы, должны быть отмечены как абстрактные. Порожденный класс может реализовывать также дополнительные интерфейсы.

 

Полиморфизм методов Способность классов поддерживать различные реализации методов с одинаковыми именами – один из способов реализации полиморфизма. Различные реализации методов с одинаковыми именами в Java называется перегрузкой методов. На языках, которые не поддерживают перегрузку методов, каждому методу необходимо давать уникальное имя. На практике часто приходится реализовывать один и тот же метод для различных типов данных. Право выбора специфической версии метода предоставлено компилятору.

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

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

 

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

 

Пример, который иллюстрирует динамическую диспетчеризацию методов (файл Dispatch.java):

 

class A

{

 void callme()

 {

  System.out.println(Метод callme класса A”);

 }

}

class B extends A

{

 //Переопределить callme

 void callme()

 {

  System.out.println(Метод callme класса B”);

 }

}

class C extends A

{

 //Переопределить callme

 void callme()

 {

  System.out.println(Метод callme класса С”);

 }

}

class Dispatch

{

 public static void main(String args[])

 {

  A a = new A();        //объект типа A

  B b = new B();        //объект типа B

  C c = new C();        //объект типа C

  A r;                  //определить ссылку типа A

 

  r = a;                //r указывает на A-объект

  r.callme();           //вызывает A-версию callme

 

  r = b;                //r указывает на B-объект

  r.callme();           //вызывает B-версию callme

 

  r = c;                //r указывает на C-объект

  r.callme();           //вызывает C-версию callme

 }

}

 

Вывод программы:

 

Метод callme класса A

Метод callme класса B

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

 

В Java все методы используют позднее связывание, если вы не отметите их явно как final. Финальные методы не могут быть переопределены и вызываются быстрее. Тот факт, что в Java по умолчанию используется позднее связывание, тогда как в C++ стандартом является раннее связывание, – явный признак разного подхода языков: C++ временами жертвует объектно-ориентированной моделью в пользу эффективности, тогда как Java – наоборот.

 

Полиморфизм через динамическое определение типов (RTTI)

Java позволяет узнать точный тип объекта, когда у вас есть ссылка только на базовый тип. Для этого в Java встроено безопасное преобразование типов (type-safe downcast). Cинтаксис безопасного преобразования типов:

 

Dog MyDog = (Dog) myAnimal;

 

В случае ошибки выбрасывается исключение.

 

Полиморфизм представлений Известно, что в ряде ситуаций полезен "полиморфизм представлений", когда один объект имеет несколько представлений, оптимизированных для выполнения специфических операций. В идеале эти представления должны поддерживаться на протяжении всего жизненного цикла объекта. Авторы Java предложили частичное решение проблемы полиморфизма представлений, введя "копирующие" конструкторы, создающие новый экземпляр коллекции из элементов существующего набора, быть может, отличающегося реализацией. Например, конструктор TreeSet(Collection c) позволяет представить коллекцию c в виде экземпляра класса TreeSet.

 

 

 

Ссылки:

 

1. Эккель Брюс. Thinking in Java 2nd edition – Полиморфизм http://dmitry.ints.net/library/prog/link/Java/Java/Chapter07.html

2. Шилдт Г. Java 2, v5.0 (Tiger). Новые возможности: Пер. с англ. – СПб.: БХВ-Петербург, 2005. – 208 с.

3. Jet Infosystems. Новое в языке Java. http://jetinfo.isib.ru/1998/11-12/1/article1.11-12.199831.html

 

 

Автор:

 

 

Загребин Виктор Александрович

 

 

< Раздел “Язык Java > < Раздел “Технологии Java > < Основная страница >

 

Hosted by uCoz