Урок 63 - Методы, наследование классов, операции с классами Delphi, (часть 5/6)

  Давайте, например, построим два класса-наследника нашего класса TPerson. Они будут конкретизировать сведения об абстрактной личности, которую представляет класс TPerson. Один класс-наследник TStudent пусть представляет студента, а другой класс TEmpl представляет сотрудника некоторой организации. Объявления этих классов могут выглядеть так:

TStudent = class(TPerson)
 public
  function PersonToStr: string;
 end;

TEmpl = class(TPerson)
 public
  function PersonToStr: string;
end;

  Эти классы наследуют все свойства и методы своего базового класса TPerson. В обоих классах объявлены новые открытые методы PersonToStr. Предполагается, что их назначение - представить информацию о человеке в виде единой строки. Такая строка полезна во многих случаях. В частности, например, для подготовки шапки характеристики, как в приложении, которое вы разрабатывали в разд. 1.3.
Реализация этих методов может иметь вид:

function TStudent.PersonToStr: string; 
const 
	Unknown = 'неизвестный'; 
	var S: string;
begin
	S := FName + ' , '; 
	
	if FYear = 0 then 
		S := S + Unknown 
	else 
		S := S + IntToStr(FYear); 
		
	S : = S + ' г.p., ' ; 
	if FSex = 'ж’ then 
		S := S + 'студентка' 
	else 
		S := S + 'студент';
		
	S := S + ' группы ' + FDepl + ' института ' + FDep2;  
	Result := S; 
end;

function TEmpl.PersonToStr: string; 
const 
	Unknown = 'неизвестный'; 
var 
	S: string; 
begin
	S := FName + ', '; 
	if FYear = 0 then 
		S := S + Unknown 
	else 
		S := S + IntToStr(FYear);
		
	S := S + ' r.p., ';
	 if FSex = 'ж' then 
		S := S + 'сотрудница' 
	 else
		S := S + 'сотрудник'; 
		
	S := S + ' отдела ' + FDepl + ' организации ' +	FDep2;
	Result := S; 
end;

  Комментарии к этому коду, наверное, излишни. Имеет смысл сказать только о смысле свойств Depl и Dep2 в новых классах. Как видно из кода, свойство Depl в классе TStudent указывает студенческую группу, а в классе TEmpl - отдел. Свойство Dep2 указывает организацию (институт), в которой работает (учится) человек. Вы можете, конечно, воспринимать свойства методов иначе и соответственно переделать приведенные функции.

  Можете добавить в ваше тестовое приложение еще одно окно Edit для задания свойства Dep2. Но главное сейчас - посмотреть соотношение родительского и производных классов.
  Можете оставить прежнее объявление
var Pers: TPerson; но при создании объекта указать какой-то производный класс, например:

Pers := TStudent.Create;

  Все будет работать, т.е. производный класс присвоится переменной родительского класса. Но если вы попробуете записать оператор вида:
ShowMessage(Pers.PersonToStr);
то получите сообщение об ошибке:

«Undeclared identifier: 'PersonToStr'»,

поскольку в классе TPerson не объявлен метод PersonToStr. Но все будет нормально, если вы измените этот оператор следующим образом:

ShowMessage((Pers as TStudent).PersonToStr);

  В этом операторе вы используете операцию as, определенную для классов. Ее первым операндом является объект, вторым - класс. Если А — объект, а С -класс, то выражение A as С возвращает тот же самый объект, но рассматриваемый как объект класса С (В смысле: у объекта А будут свойства и методы объекта С). Операция даст результат, если указанный класс С является классом объекта А или одним из наследников этого класса. В нашем случае это условие соблюдается, так что операция as возвращает объект Pers, рассматриваемый как объект TStudent. А в таком объекте метод PersonToStr имеется.   Если бы вы сразу объявили переменную Pers класса TStudent:

var Pers: TStudent;

то операция as не потребовалась бы. Выражение Pers.PersonToStr было бы воспринято нормально.

  Для классов определена еще одна операция - is. Выражение A is С позволяет определить, относится ли объект А к классу С или к одному из его потомков. Если относится, то операция is возвращает true, в противном случае - false. Например, в нашем примере при любом объявлении класса создаваемого объекта Pers выражение Pers is TPerson вернет true. Но выражение Pers is TStudent вернет true, если объект создан как объект TStudent, и вернет false, если объект создан как объект TPerson.

  Теперь посмотрим наследование методов. Давайте введем метод PersonToStr не только в производные, но и в базовый класс TPerson. Для этого класса его реализация может быть очень простой:

function TPerson.PersonToStr: string; begin Result := FName; end;

  Теперь метод PersonToStr объявлен с одним и тем же именем и в родительском, и в производных классах. Иначе говоря, вы переопределили или перегрузили родительский метод в производных классах. Теперь вы сможете увидеть, что выражение Pers.PersonToStr будет всегда нормально срабатывать.

   Но вызываться будет метод того класса, который указан в объявлении переменной Pers. Если она объявлена как переменная класса TPerson, то всегда будет вызываться метод этого класса, даже если вы занесли в эту переменную указатель на объект класса TStudent или TEmpl. Если вы объявите переменную Pers класса TStudent, и занесете в нее указатель на объект класса TStudent, то вызываться будет метод этого класса. Если вы все-таки хотите в этом случае вызвать метод родительского класса, надо применить к переменной Pers явное приведение типа:

TPerson(Pers).PersonToStr

   При реализации метода, переопределенного любым способом в классе-наследнике, можно вызывать метод класса-родителя. Для этого перед именем метода при его вызове записывается ключевое слово inherited. Например, оператор

inherited PersonToStr;

вызывает метод PersonToStr родительского класса.

  Если записать слово inherited и после него не писать имя вызываемого метода, то будет вызываться наследуемый метод, совпадающий по имени с именем того метода, из которого он вызывается. Например, если в переопределяемом конструкторе встречается оператор inherited; то будет вызван конструктор родительского класса. Этим мы уже пользовались при написании конструкторов и деструкторов класса TPerson.

   В следуйшем уроке мы окунёмся в самые дебри классов.

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




Добавил(а): Programer Дата: 2013-07-17
Может следующий урок посвятить ИИ-Искусственному Интеллекту ?


  1. сергей
    сергей a year ago
    Комментарии никогда не бывают лишними!!! Повторенье мать ученья! Вы учите писать код, а кто научит его читать?? Да! Навык чтения будет в процессе, но это уже будет позже чем требуется уже(((
  2. сергей
    сергей a year ago
    А в целом из того что лежит в интернете здесь достаточно подробно всё расписано,,,, Автору большая благодарность))))
Отменить.