#27 Переопределение методов классов в Паскале. ООП

Переопределение метода - возможность в поддерживающих ООП языках программирования изменить поведение метода из наследуемого родительского класса в классе-потомке

Рассмотрим пример:

type
  Cat = class  // родительский класс
  public
    constructor create(nameValue: string);
    procedure sayHello();

  strict protected
    name: string;
  end;

  Tiger = class(Cat) // класс-потомок
  end;

constructor Cat.create(nameValue: string);
begin
 self.name := nameValue;
end;

procedure Cat.sayHello();
begin
 writeln('Привет, я '  + self.name + '!');
end;


var
  CatItem: Cat;
  TigerItem: Tiger;
begin
  CatItem := Cat.create('Мурка');
  CatItem.sayHello();

  TigerItem := Tiger.create('Шархан');
  TigerItem.sayHello();
end.

-- что если мы хотим, чтобы все тигры при приветствии (в отличии от кошек) добавляли перед своим имененем слово "тигр", этого можно добавить переопределением метода sayHello()

type
  Cat = class  // родительский класс
  public
    constructor create(nameValue: string);
    procedure sayHello();

  strict protected
    name: string;
  end;

  Tiger = class(Cat) // класс-потомок
    procedure sayHello(); // переопределяемый метод
  end;

constructor Cat.create(nameValue: string);
begin
 self.name := nameValue;
end;

procedure Cat.sayHello();
begin
 writeln('Привет, я '  + self.name + '!');
end;

// реализация переопределяемого в потомке метода
procedure Tiger.sayHello();
begin
 writeln('Привет, я тигр '  + self.name + '!');
end;

var
  CatItem: Cat;
  TigerItem: Tiger;
begin
  CatItem := Cat.create('Мурка');
  CatItem.sayHello();

  TigerItem := Tiger.create('Шархан');
  TigerItem.sayHello();
end.

-- таким образом:
мы реализовали в классе Tiger собственную версию процедуры sayHello(), переопределив ее поведение
клиентский код остался прежним (вызываем метод с тем же именем как и раньше), но теперь выполняется код не из родительского класса, а из класса-потомка

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

  • если реализация есть в самом классе - то она берется из него
  • если в ннепосредственном родителе (как в примере выше), то из родителя
  • если в "классе-дедушке" (т.е. в родителе родительского класса) -то его

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

Несколько элементов в цепочке наследования

Как уже было сказано выше, в цепочке наследования для класса, может быть более 2 элементов, напр. ниже их три:

type
  Cat = class  // базовый родительский класс
  public
    constructor create(nameValue: string);
    procedure sayHello();

  strict protected
    name: string;
  end;

  Tiger = class(Cat) // класс-потомок Cat
  public
    procedure sayHello();
  end;

  AmurTiger = class(Tiger) // класс-потомок Tiger
    procedure sayHello();
  end;

constructor Cat.create(nameValue: string);
begin
 self.name := nameValue;
end;

procedure Cat.sayHello();
begin
 writeln('Привет, я '  + self.name + '!');
end;

procedure Tiger.sayHello();
begin
 writeln('Привет, я тигр '  + self.name + '!');
end;

procedure AmurTiger.sayHello();
begin
 writeln('Привет, я амурский тигр '  + self.name + '!');
end;


var
  CatItem, MyCat: Cat;
  TigerItem: Tiger;
  MyTiger: AmurTiger;
begin
  CatItem := Cat.create('Мурка');
  CatItem.sayHello();

  MyCat := Cat.create('Мурзик');
  MyCat.sayHello();

  TigerItem := Tiger.create('Шархан');
  TigerItem.sayHello();

  MyTiger := AmurTiger.create('Шархан2');
  MyTiger.sayHello();
end.                   

-- тут Амурский Тигр наследуется от класс Тигр, который в свою очередь наследуется от класса "Кошка" (Cat).

vedro-compota's picture

type
Cat = class // родительский класс
public

constructor create(nameValue: string);
procedure sayHello();

strict protected
name: string;
end;

Tiger = class(Cat) // класс-потомок
public
procedure sayHello();
end;

AmurTiger = class(Tiger) // класс-потомок Tiger
procedure sayHello();
end;

constructor Cat.create(nameValue: string);
begin
self.name := nameValue;
end;

procedure Cat.sayHello();
begin
writeln('Привет, я ' + self.name + '!');
end;

procedure Tiger.sayHello();
begin
writeln('Привет, я тигр ' + self.name + '!');
end;

procedure AmurTiger.sayHello();
begin
writeln('Привет, я амурский тигр ' + self.name + '!');
end;

var
CatItem, MyCat: Cat;
TigerItem: Tiger;
MyTiger: AmurTiger;
begin
CatItem := Cat.create('Мурка');
CatItem.sayHello();

MyCat := Cat.create('Мурзик');
MyCat.sayHello();

TigerItem := Tiger.create('Шархан');
TigerItem.sayHello();

MyTiger := AmurTiger.create('Шархан2');
MyTiger.sayHello();
end.

// -----------------

type
Human = class // родительский класс
public
procedure sayHello();
procedure sayHello(name: string);
procedure sayHello(name, surname: string);
end;

procedure Human.sayHello();
begin
writeln('Привет, я человек!');
end;

procedure Human.sayHello(name: string);
begin
writeln('Привет, я ' + name + '!');
end;

procedure Human.sayHello(name, surname: string);
begin
writeln('Привет, я ', name, ' ', surname, '!');
end;

var
Man: Human;
begin
Man := Human.create();
Man.sayHello();
Man.sayHello('Вася');
Man.sayHello('Вася', 'Петров');
end.

// смешанный переопределения и перегрузки

type
  Human = class  // родительский класс
  public
    procedure sayHello();
    procedure sayHello(name: string);
    procedure sayHello(name, surname: string);
  end;

  ModernHuman = class(Human)
    procedure sayHello();
    procedure sayHello(name: string);
  end;

procedure Human.sayHello();
begin
 writeln('Привет, я человек!');
end;

procedure Human.sayHello(name: string);
begin
 writeln('Привет, я ' + name + '!');
end;

procedure Human.sayHello(name, surname: string);
begin
 writeln('Привет, я ', name, ' ', surname, '!');
end;

procedure ModernHuman.sayHello(name: string);
begin
 writeln('Привет, я житель XXI века ' + name + '!');
end;

procedure ModernHuman.sayHello();
begin
 writeln('Привет, я житель XXI века!');
end;

var
  Man: Human;
  NewMan: ModernHuman;
begin
  Man := Human.create();
  Man.sayHello();
  Man.sayHello('Вася');
  Man.sayHello('Вася', 'Петров');

  NewMan := ModernHuman.create();
  NewMan.sayHello();
  NewMan.sayHello('Вася');
end.

_____________
матфак вгу и остальная классика =)