Наследование

В зависимости от того, какие действия происходят при вызове, методы делятся на следующие группы:

  • статические методы;
  • виртуальные методы;
  • динамические методы.

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

Пример был взят из учебника Free Pascal и Lazarus (Е.Р. Алексеев, О.В. Чеснокова, Т.В. Кучер), где он описан для среды Lazarus и с графическим интерфейсом.

Здесь приводится для IDE Free Pascal.

program project1;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };
 
type TTriangle = class
  Private
    x,y: array[0..2] of real;
  Public
    constructor Create;
    procedure Set_Tr(a,b: array of real);
    function a():real;
    function b():real;
    function c():real;
    function Proverka():boolean; virtual;
    function Perimetr():real;
    function Square():real;
    procedure Show(); virtual;
end;
type R_TTriangle = class(TTriangle)
  Public
    function Proverka():boolean; override;
    procedure Show(); override;
end;
constructor TTriangle.Create;
  var i: integer;
  begin
    for i:=0 to 2 do begin
      x[i]:=0; y[i]:=0;
    end;
  end;
procedure TTriangle.Set_Tr(a,b: array of real);
  var i: integer;
  begin
    for i:=0 to 2 do begin
      x[i]:=a[i]; y[i]:=b[i];
    end;
  end;
function TTriangle.a():real;
  begin
    a := sqrt(sqr(x[1]-x[0]) + sqr(y[1]-y[0]));
  end;
function TTriangle.b():real;
  begin
    b := sqrt(sqr(x[2]-x[1]) + sqr(y[2]-y[1]));
  end;
function TTriangle.c():real;
  begin
    c := sqrt(sqr(x[0]-x[2]) + sqr(y[0]-y[2]));
  end;
function TTriangle.Perimetr():real;
  begin
    Perimetr := a() + b() + c();
  end;
function TTriangle.Square():real;
  var p: real;
  begin
    p := Perimetr()/2;
    Square := sqrt((p-a()) * (p-b()) * (p-c()));
  end;
function TTriangle.Proverka():boolean;
  begin
    if (x[0]-x[1])/(x[0]-x[2])= (y[0]-y[1])/(y[0]-y[2]) then
      Proverka := false
    else Proverka := true;
  end;
procedure TTriangle.Show();
  begin
    if Proverka() then begin
      writeln('a=',a(),', b=',b(),', c=',c());
      writeln('P=',Perimetr(),', S=',Square());
    end;
  end;
function R_TTriangle.Proverka():boolean;
  begin
    if (a()=b()) and (c()=b()) then
      Proverka := false
    else Proverka := true;
  end;
procedure R_TTriangle.Show();
  begin
    if Proverka() then begin
      writeln('a=',a());
      writeln('P=',Perimetr(),', S=',Square());
    end;
  end;
var
  figura1: TTriangle;
  figura2: R_TTriangle;
  var x1,y1,x2,y2: array[1..3] of real;
begin
  write('1 coords: '); readln(x1[1],y1[1]);
  write('2 coords: '); readln(x1[2],y1[2]);
  write('3 coords: '); readln(x1[3],y1[3]);
  write('1 coords: '); readln(x2[1],y2[1]);
  write('2 coords: '); readln(x2[2],y2[2]);
  write('3 coords: '); readln(x2[3],y2[3]);
  figura1 := TTriangle.Create;
  figura2 := R_TTriangle.Create;
  figura1.Set_Tr(x1,y1);
  figura2.Set_Tr(x2,y2);
  figura1.Show();
  figura2.Show();
  figura1.Free;
  figura2.Free;
readln;
end.

Вторая программа с демонстрацией наследования:

program project1;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };
 
type TFigure = class
  private
    n: integer; // количество сторон
    p: array of real; // массив длин сторон
  public
    // абстрактные подпрограммы
    // в каждом производном классе будут перегружаться
    constructor Create; virtual; abstract;
    function Perimeter(): real;
    function Square(): real; virtual; abstract;
    procedure Show(); virtual; abstract;
end;
type TCircle = class(TFigure)
  public
    constructor Create; override;
    function Perimeter(): real;
    function Square(): real; override;
    procedure Show(); override;
end;
type TRectangle = class(TFigure)
  public
    constructor Create; override;
    function Square(): real; override;
    procedure Show(); override;
end;
function TFigure.Perimeter(): real;
  var i: integer;
      s: real;
  begin
    s := 0;
    for i:=0 to n-1 do
        s := s + p[i] + p[i];
    Perimeter := s;
  end;
 
constructor TCircle.Create;
  begin
    n := 1;
    SetLength(p,n); // выделяем память под 1 элемент массива
    p[0] := 5; // радиус окружности
  end;
function TCircle.Perimeter(): real;
  begin
    Perimeter := 2 * PI * p[0]; // длина окружности
  end;
function TCircle.Square(): real;
  begin
    Square := PI * sqr(p[0]);
  end;
procedure TCircle.Show();
  begin
    writeln('r=',p[0]:4:2,' P=',Perimeter():4:2, ' S=', Square():4:2);
  end;
 
constructor TRectangle.Create;
  begin
    n := 2;
    SetLength(p,n); // выделяем память под 2 элемента
    p[0] := 4; p[1] := 2;
  end;
function TRectangle.Square(): real;
  begin
    Square := p[0] * p[1];
  end;
procedure TRectangle.Show();
  begin
    writeln('a=',p[0]:4:2,' b=',p[1]:4:2,' P=',Perimeter():4:2, ' S=', Square():4:2);
  end;
 
var
    figura1: TCircle;
    figura2: TRectangle;
begin
  figura1 := TCircle.Create;
  figura2 := TRectangle.Create;
  figura1.Show();
  figura2.Show();
readln
end.

Добавить комментарий

CAPTCHA
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
CAPTCHA на основе изображений
Введите символы, которые показаны на картинке.