Основы программирования — второй семестр 08-09; Михалкович С.С.; VIII часть — различия между версиями

Материал из Вики ИТ мехмата ЮФУ
Перейти к: навигация, поиск
(Позднее связывание и виртуальные методы)
(Полиморфизм и виртуальные методы)
Строка 1: Строка 1:
 
== Полиморфизм и виртуальные методы ==
 
== Полиморфизм и виртуальные методы ==
 
=== Вводные понятия ===
 
=== Вводные понятия ===
'''Инкапсуляция''' — хранение в классе одновременно данных и методов (класс представляет собой «капсулу»). <br />
+
:'''Инкапсуляция''' — хранение в классе одновременно данных и методов (класс представляет собой «капсулу»). <br />Инкапсуляция тесно связана с защитой данных: лишь некоторые члены в этой «капсуле» являются открытыми.
Инкапсуляция тесно связана с защитой данных: лишь некоторые члены в этой «капсуле» являются открытыми.
 
  
'''Полиморфизм''' — это, дословно, многообразие форм. <br />
+
:'''Полиморфизм''' — это, дословно, многообразие форм. <br />Более точно, '''полиморфизм''' — это способность родственных классов выполнять одинаковые действия сходным образом.
Более точно, '''полиморфизм''' — это способность родственных классов выполнять одинаковые действия сходным образом.
 
  
 
''<u>Пример</u>.'' <br />
 
''<u>Пример</u>.'' <br />
Строка 28: Строка 26:
 
<u>Вопрос</u>: какой метод <tt>Print</tt> вызовется? <br />
 
<u>Вопрос</u>: какой метод <tt>Print</tt> вызовется? <br />
 
<u>Ответ</u>: В разных языках программирования вызовутся <tt>Print</tt> разных классов:
 
<u>Ответ</u>: В разных языках программирования вызовутся <tt>Print</tt> разных классов:
:в таких языках, как ''Java'', ''Eiffel'' — <tt>'''Student'''.Print</tt>, <br />а в ''C++'', ''C#'', ''PasacalABC.NET'' — <tt>'''Person'''.Print</tt>.
+
* в таких языках, как ''Java'', ''Eiffel'' — <tt>'''Student'''.Print</tt>
 +
* а в ''C++'', ''C#'', ''PasacalABC.NET'' — <tt>'''Person'''.Print</tt>
  
 
Т.о. в ''PascalABC.NET'' вызовется метод <tt>Person.Print</tt>, но, хотелось бы, чтобы вызывался метод <tt>Student.Print</tt>.
 
Т.о. в ''PascalABC.NET'' вызовется метод <tt>Person.Print</tt>, но, хотелось бы, чтобы вызывался метод <tt>Student.Print</tt>.
  
Если решение о том, какой метод вызывать, принимается на этапе ''компиляции'' (<u>рано</u>), то связывание имени метода с конкретным кодом называется '''ранним связыванием'''.
+
: Если решение о том, какой метод вызывать, принимается на этапе ''компиляции'' (<u>рано</u>), то связывание имени метода с конкретным кодом называется '''ранним связыванием'''.
  
Если же решение о том, какой метод вызывать, принимается на этапе ''выполнения программы'' (<u>поздно</u>), то связывание имени метода с конкретным кодом называется '''поздним связыванием'''. <br />
+
: Если же решение о том, какой метод вызывать, принимается на этапе ''выполнения программы'' (<u>поздно</u>), то связывание имени метода с конкретным кодом называется '''поздним связыванием'''. <br />Позднее связывание осущесвляется с методом того класса, на который ссылается переменная в процессе выполнения программы.
Позднее связывание осущесвляется с методом того класса, на который ссылается переменная в процессе выполнения программы.
 
  
 
Итак, в ''PascalABC.NET'' по умолчанию реализовано '''''раннее связывание'''''.
 
Итак, в ''PascalABC.NET'' по умолчанию реализовано '''''раннее связывание'''''.
Строка 83: Строка 81:
 
'''Полиморфизм''' в объектно-ориентированных программирования реализуется через механизм '''''виртуальных методов'''''.
 
'''Полиморфизм''' в объектно-ориентированных программирования реализуется через механизм '''''виртуальных методов'''''.
  
Переменная базового класса, содержащая виртуальные методы, называется '''полиморфной переменной'''.  <br />
+
:Переменная базового класса, содержащая виртуальные методы, называется '''полиморфной переменной'''.  <br />Она имеет '''''статический''''' тип (заявленный при объявлении) и '''''динамический''''' (тип объекта, на который она ссылается в данный момент выполнения программы).
Она имеет '''''статический''''' тип (заявленный при объявлении) и '''''динамический''''' (тип объекта, на который она ссылается в данный момент выполнения программы).
 
  
 
'''Замечание.''' Обычная подпрограмма также может быть ''полиморфной''. <br />
 
'''Замечание.''' Обычная подпрограмма также может быть ''полиморфной''. <br />
Строка 97: Строка 94:
 
</source>
 
</source>
  
Обычная подпрограмма называется '''полиморфной''', если она содержит хотя бы один полиморфный параметр.
+
:Обычная подпрограмма называется '''полиморфной''', если она содержит хотя бы один полиморфный параметр.
  
 
=== Виртуальные методы как блоки замены кода ===
 
=== Виртуальные методы как блоки замены кода ===

Версия 15:26, 21 мая 2009

Полиморфизм и виртуальные методы

Вводные понятия

Инкапсуляция — хранение в классе одновременно данных и методов (класс представляет собой «капсулу»).
Инкапсуляция тесно связана с защитой данных: лишь некоторые члены в этой «капсуле» являются открытыми.
Полиморфизм — это, дословно, многообразие форм.
Более точно, полиморфизм — это способность родственных классов выполнять одинаковые действия сходным образом.

Пример.
Есть класс

Студент
    Готовиться_к_экзамену()

И два его наследника:

Хороший_студент
    Готовиться_к_экзамену()

и

Плохой студент
    Готовиться_к_экзамену()

Действие Готовиться_к_экзамену() они выполняют по-разному.

Рассмотрим следующий код:

var p: Person;
p := new Student('Иванов', 17, 1, 11);
p.Print();

Вопрос: какой метод Print вызовется?
Ответ: В разных языках программирования вызовутся Print разных классов:

  • в таких языках, как Java, EiffelStudent.Print
  • а в C++, C#, PasacalABC.NETPerson.Print

Т.о. в PascalABC.NET вызовется метод Person.Print, но, хотелось бы, чтобы вызывался метод Student.Print.

Если решение о том, какой метод вызывать, принимается на этапе компиляции (рано), то связывание имени метода с конкретным кодом называется ранним связыванием.
Если же решение о том, какой метод вызывать, принимается на этапе выполнения программы (поздно), то связывание имени метода с конкретным кодом называется поздним связыванием.
Позднее связывание осущесвляется с методом того класса, на который ссылается переменная в процессе выполнения программы.

Итак, в PascalABC.NET по умолчанию реализовано раннее связывание.

Позднее связывание и виртуальные методы

Чтобы обеспечить позднее связывание в языке Pascal, соответствующие методы надо сделать виртуальными в базовом классе.

type
  Person = class
  ...
  public
    ...
    procedure Print; virtual;
    begin
      WriteFormat('Имя: {0}  Возраст: {1}  ', 
        fName, fAge);
    end;
  end;
  
  Student = class(Person)
  ...
  public
    procedure Print; override;
    begin
      inherited Print;
      WriteFormat('Курс: {0}  Группа: {1}  ', 
        fCourse, fGroup);
    end;
  end;

При переопределении виртуального метода в классе-потомке используется ключевое слово override.

Примечание. Переопределяющий виртуальный метод должен иметь те же параметры и тот же тип возвращаемого значения.

Вернемся к рассмотренному ранее коду:

var p: Person;
p := new Student('Иванов', 17, 1, 11);
p.Print();

Теперь решение о том, какой метод вызывать, будет отложено до этапа выполнения, и будет вызвано Print того класса, на объект которого ссылается переменная в текущий момент (в данном случае — для Student).

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

Полиморфизм в объектно-ориентированных программирования реализуется через механизм виртуальных методов.

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

Замечание. Обычная подпрограмма также может быть полиморфной.
Пример.

procedure Print(p: Person);
begin
  p.Print(); // обращение полиморфизма
end;
...
Print(new Student(...));
Обычная подпрограмма называется полиморфной, если она содержит хотя бы один полиморфный параметр.

Виртуальные методы как блоки замены кода

Класс Object — неявный предок всех классов .NET

Переопределение методов Equals и ToString в классах Person и Student

Цепочка виртуальности и её разрыв

Алгоритм поиска в цепочке виртуальности