Урок 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 | |
Может следующий урок посвятить ИИ-Искусственному Интеллекту ?
![]() ![]() |
-
Комментарии никогда не бывают лишними!!! Повторенье мать ученья! Вы учите писать код, а кто научит его читать?? Да! Навык чтения будет в процессе, но это уже будет позже чем требуется уже(((
-
А в целом из того что лежит в интернете здесь достаточно подробно всё расписано,,,, Автору большая благодарность))))