Урок 64 - Виртуальные методы, полиморфизм, абстрактные классы, (часть 6/6)

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

  Все это мы видели на примерах в предыдущем разделе. Но представим себе такую задачу. Вы объявили в приложении массив объектов типа TPerson:
var PersArray: array[1..10] of TPerson;

  Далее заполняете этот массив вперемешку объектами классов TStudent и TEmpl, т.е. создаете, например, общий список учащихся и преподавателей. В разд. 3.5.4 вы видели, что это возможно, так как переменная базового класса может принимать объекты производных классов. А затем хотите пройти в цикле элементы этого массива и отобразить в окне Memo информацию о них:

for i:=l to 10 do Memol.Lines.Add(PersArray[i].PersonToStr);

  Или аналогичная задача с использованием списка TList:
объявлена переменная var List: TList; в нее заносятся указатели на объекты классов TStudent и TEmpl, а затем вы хотите пройти в цикле элементы этого списка и отобразить их в окне Memo:

for i:=0 to List.Count - 1 do Memol.Lines.Add(TPerson(List[i]).PersonToStr);

  Реализуйте один из этих вариантов (не забудьте при завершении приложения удалять объекты из памяти), и посмотрите, что получится. А получится очевидный результат: во всех случаях сработает метод PersonToStr родительского класса TPerson, так как соответствующие объекты объявлены объектами этого класса. И программа, естественно, не знает, объекты какого класса хранятся в массиве или в списке.

  Конечно, можно усложнить код, проверять каждый раз операцией is истинный класс объекта, и указывать операцией as этот класс (см. об этих операциях в разд. 3.5.4). Для массива это будет выглядеть так:

if PersArrayfi] is TStudent then 
 Memol.Lines.Add((PersArray[i] as TStudent).PersonToStr)
  else 
if PersArray[i] is TEmpl then 
 Memol.Lines.Add((PersArray[i] as TEmpl).PersonToStr);

  А для списка аналогичный код имеет вид:


if  TPerson(List[i])   is  TStudent then    Memol.Lines.Add(TStudent(List[i]).PersonToStr) 
 else  
 if  TPerson(List[i]) is TEmpl then    Memol.Lines.Add(TEmpl(List[i]).PersonToStr);

  Задача будет решена, но некрасиво. Во-первых, код усложняется. А во-вторых, если вы впоследствии решите создать какие-то новые классы, производные от TPerson, вам придется вводить соответствующие дополнительные проверки в эти коды.

  Красивое решение подобных задач обеспечивается очень легко с помощью виртуальных методов. Виртуальные методы не связаны с другими методами с тем же именем в классах-наследниках. Если в классах-наследниках эти методы перегружены, то при обращении к такому методу во время выполнения будет вызываться тот из методов с одинаковыми именами, который соответствует истинному классу объекта. В приведенных примерах, если сделать методы PersonToStr виртуальными, то операторы

Memol.Lines.Add(PersArray[i].PersonToStr); Memol.Lines.Add(TPerson(List[i]).PersonToStr);

  будут автоматически вызывать методы PersonToStr того класса (TStudent, TEmpl или других производных от TPerson), к которому относится каждый объект. Такой подход, облегчающий работу с множеством родственных объектов, называется полиморфизмом.

   Сделать метод родительского класса виртуальным очень просто. При объявлении в классе виртуальных методов после точки с занятой, завершающей объявление метода, добавляется ключевое слово virtual. Например, чтобы объявить в базовом классе TPerson метод PersonToStr виртуальным, надо в его объявление добавить слово virtual:

function PersonToStr: string; virtual;

  Чтобы перегрузить в классе-наследнике виртуальный метод, надо после его объявления поставит ключевое слово override. В наших примерах объявления метода в классах и должны выглядеть так:

function PersonToStr: string; override;
И это все! Методы стали виртуальными и приведенные в начале данного раздела операторы, будут работать безо всяких проверок if.

  Если в каком-то базовом классе метод был объявлен как виртуальный, то он остается виртуальным во всех классах-наследниках (в частности, и в наследниках классов наследников). Однако обычно для облегчения понимания кодов, перегруженные методы принято повторно объявлять виртуальными, чтобы была ясна их суть для тех, кто будет строить наследников данного класса. Например:

function PersonToStr: string; override; virtual;

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

  Объявляется абстрактный метод с помощью ключевого слова abstract после слова virtual. Например, вы можете в классе TPerson объявить метод PersonToStr следующим образом:

function PersonToStr: string; virtual; abstract;

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

Удачи!
Встретимся в следующем уроке!




Добавил(а): Programer Дата: 2013-08-04
Эй уже кто-нибудь ответит мне ?


  1. JbjTU
    JbjTU 14 days ago
    Medicament information leaflet. Cautions. <a href="https://prednisone4u.top">order generic prednisone price</a> in Canada. Actual information about drug. Get here.
    [url=https://studybscnursinginbangalore.com/sankara-academy-of-vision]Some about medicines.[/url] [url=http://134.236.247.147/eof/code/login/guestbook.php]All information about medicines.[/url] [url=https://lensesonline.kz/product/64/?rating=1]Actual what you want to know about pills.[/url] a706a28
  2. veomveiwkn
    veomveiwkn 9 days ago
    Урок 64 - Виртуальные методы, полиморфизм, абстрактные классы Delphi, (часть 6/6) - The Delphi
    [url=http://www.g8dmw8w7r6km0p883jmg770vl9i77e55s.org/]uveomveiwkn[/url]
    veomveiwkn http://www.g8dmw8w7r6km0p883jmg770vl9i77e55s.org/
    <a href="http://www.g8dmw8w7r6km0p883jmg770vl9i77e55s.org/">aveomveiwkn</a>
  3. nqzndn
    nqzndn 7 days ago
    Урок 64 - Виртуальные методы, полиморфизм, абстрактные классы Delphi, (часть 6/6) - The Delphi
    [url=http://www.g0ow5n2r1556zt9r8v3b403grb1zzh75s.org/]unqzndn[/url]
    <a href="http://www.g0ow5n2r1556zt9r8v3b403grb1zzh75s.org/">anqzndn</a>
    nqzndn http://www.g0ow5n2r1556zt9r8v3b403grb1zzh75s.org/
  4. arufivi
    arufivi 6 days ago
    [url=http://mewkid.net/when-is-xuxlya2/]Amoxicillin 500 Mg[/url] <a href="http://mewkid.net/when-is-xuxlya2/">Amoxicillin 500mg</a> dwn.mhqp.thedelphi.ru.bzo.ox http://mewkid.net/when-is-xuxlya2/
  5. oqheqovd
    oqheqovd 6 days ago
    [url=http://mewkid.net/when-is-xuxlya2/]Amoxicillin[/url] <a href="http://mewkid.net/when-is-xuxlya2/">Amoxicillin Without Prescription</a> klg.drmm.thedelphi.ru.hzv.wk http://mewkid.net/when-is-xuxlya2/
  6. tapeyec
    tapeyec 6 days ago
    [url=http://mewkid.net/when-is-xuxlya2/]Buy Amoxicillin Online[/url] <a href="http://mewkid.net/when-is-xuxlya2/">Amoxicillin</a> scs.crxy.thedelphi.ru.nmg.hf http://mewkid.net/when-is-xuxlya2/
  7. unahigi
    unahigi 6 days ago
    [url=http://mewkid.net/when-is-xuxlya2/]Buy Amoxicillin[/url] <a href="http://mewkid.net/when-is-xuxlya2/">Amoxicillin Online</a> wrs.xzya.thedelphi.ru.jay.jh http://mewkid.net/when-is-xuxlya2/
Отменить.