Файл: 8. Переопределение методов. Полиморфные (виртуальные) методы.pdf

Добавлен: 20.10.2018

Просмотров: 1198

Скачиваний: 10

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

 

 

 

Фрагмент  UML-диаграммы  классов  для  улучшенной  иерархии 

графических фигур теперь можно представить следующим образом. 

 

 

 

 

 

 

 

 

 

 

 

 

 

Этот  простой  пример  иллюстрирует  возможности  мощного  механизма 

динамической настройки, т.к. однажды созданный метод перемещения будет 

в дальнейшем успешно работать с объектами любых классов, лишь бы они 

входили в общую иерархию классов и реализовывали метод отображения с 

общим именем Show. 

Приведем  фрагменты  описания  классов  для  графических  фигур  с 

использованием  виртуальных  методов  (для  наглядности  убраны  директивы 

ограничения доступа). 

TFigure = class 

. . . . . 

procedure  Show;  abstractvirtual;   // реализации нет! 

procedure  MoveTo( . . . );  // обязательно дать реализацию метода! 

end; 

  Класс  Circle 
   r : integer 
  Конструктор 
  методы доступа 
  переопределенный метод Show 

 

  Класс  Rect 
  h

 

, w : integer 

  конструктор  
  методы доступа 
  переопределенный метод Show 

 

  Класс  Figure 
   x

 

, y : integer 

  Конструктор, методы доступа 
  виртуальный абстрактный метод Show 
  метод  MoveTo 

 


background image

 

 

 

TCircle = class (TFigure

procedure  Show;  override;  //  конкретная реализация для окружности! 

. . . . .                                       //   метод перемещения НЕ нужен! 

end; 

 

TRect = class (TFigure

procedure  Show;  override;  //  конкретная реализация для прямоугольника 

. . . . .                                       //   метод перемещения НЕ нужен! 

end; 

C# 

class    Figure  

  { . . . . . 

virtual   abstract   void  Show( );  // реализации нет 

void    MoveTo(int  dx,  int  dy) { Show( );  x = x + dx;  y = y + dy;  Show( ); }  

  }; 

 

class   Circle : Figure  { 

override   void   Show( ) {…}  //  конкретная реализация для окружности! 

. . . . .                                       //   метод перемещения НЕ нужен! 

 }; 

 

class   Rect : Figure  { 

override  void   Show( ) {…}  // конкретная реализация для прямоугольника 

. . . . .                                       //   метод перемещения НЕ нужен! 

 }; 

 

Java 

class   Figure   { 


background image

 

 

 . . . . . . . . . 

abstract  void  Show ( );  // виртуальный абстрактный метод 

final  void  MoveTo( . . . ) { Show( );  x = x + dx;  y = y + dy;  Show( ); } 

 }; 

 

class   Circle   extends   Figure   { 

void  Show ( ) { реализация переопределенного метода для окружности} 

. . . . .                           //   а вот метод перемещения здесь уже НЕ нужен! 

}; 

 

class   Rect  extends   Figure  { 

void   Show( ) {…}  // конкретная реализация для прямоугольника 

. . . . .                                       //   метод перемещения НЕ нужен! 

 };

 

 

Предположим,  что  в  процессе  выполнения  программы  созданы  два 

объекта-окружности  Circ1  и  Сirc2  и  два  объекта-прямоугольника  Rect1  и 

Rect2.  Тогда  в  основной  памяти  будут  выстроены  связи,  которые  условно 

можно показать с помощью следующей схемы:

 

 

 

 

 

 

 

 

 

 

 

 

объект Rect1 

объект Сirc2 

объект Rect2 

100 
100 

50 

адрес ТВМ 

для класса 

Circle 

 

50 
50 
50 

100 

адрес ТВМ для 

класса Rect 

 

200 
200 
100 

адрес ТВМ 

для класса 

Circle 

 

100 
100 
100 
100 

адрес ТВМ для 

класса Rect 

 

 адрес метода    
Show 
 

 

 адрес метода 
Show 
 

 

 код метода Show  
для класса Circle 

 

код код метода Show 
       для класса  Rect 

 

ТВМ для класса 
прямоугольников 

объект Сirc1 

ТВМ для класса 
окружностей 


background image

 

 

 

Пусть  в  программе  реализовано  несколько  обращений  к  методу 

перемещения MoveTo со стороны разных объектов: 

 Сirc1.MoveTo( ); // операцию перемещения вызывает объект-окружность 

 Rect2.MoveTo ( );  //  а теперь – объект-прямоугольник 

При  отработке  этих  вызовов  включается  механизм  динамической 

компоновки,  который  прежде  всего  определяет,  объект  какого  класса 

обращается  к  методу  перемещения.  После  этого  с  помощью  Таблицы 

Виртуальных Методов для данного класса в оперативной памяти находится 

код,  реализующий  метод  Show  именно  для  этого  класса.  Найденный 

программный код подключается к методу перемещения MoveTo. Например, 

для  перемещения  окружности    Сirc1  происходит  обращение  к  ТВМ  класса 

окружностей,  и  именно  этот  программный  код  подключается  к  MoveTo,  а 

для перемещения прямоугольника  Rect2 обращение идет уже к другой ТВМ 

и с ее помощью активизируется другой фрагмент программного кода. 

Отметим, что это еще не все преимущества использования виртуальных 

методов.  После  рассмотрения  в  следующем  разделе  использования 

полиморфизма  применительно  к  объектным  переменным  мы  вернемся  к 

примеру  с  иерархией  графических  классов  и  увидим  какие  новые 

возможности дают все эти механизмы вместе.