本文介绍了继承/多态概念的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个包含类似数据类型的二进制文件,因此我想为这两个文件创建一个统一的查看器 (TViewer).有些方法对于这两种文件类型是通用的,有些则不是.所以我创建了一个基类TShape,以及来自它的 TCircle 和 TTriangle.

I have two binary files that contain a similar type of data so I want to create a unified viewer (TViewer) for both files.Some, methods are common for these two file types, some are not. So I created a base classTShape, and the from it TCircle and TTriangle.

伪代码:

TShape = class(TObject)
  function NoOfItems: integer; virtual; abstract;
end;

TCircle = class(TShape)
  function NoOfItems: integer; override;     <---- The real implementation
end;

TTriangle = class(TShape)
  function NoOfItems: integer; override;        <---- The real implementation
end;

TViewer = class(TStringGrid)
  Container: TShape;
end;

我是这样使用的:

Procedure Main;
begin
 if FileType= Circle
 then (Viewer.Container as TCircle).Load(FileName)
 else (Viewer.Container as TTriangle).Load(FileName);

 Caption:= Viewer.Container.NoOfItems;  <---- it calls TShape which is abstract
end;

当我这样做时它有效:

if Viewer.Container is TTriangle
then Caption:= (Viewer.Container as TTriangle).NoOfItems
else ...

但我想直接这样做:

Caption:= Viewer.Container.NoOfItems;

很明显,使用 is 并没有错,只是我必须在很多地方(接近任何地方)使用它.有更好的方法来实现这个统一的查看器吗?

Obviously there is nothing wrong in using is except that I will have to use it in many many places (close to everywhere). There is a nicer way to achieve this unified viewer?

其实也可能是性能问题.我的文件包含大量项目(多达数十亿),因此进行如此多的is/as"测试实际上可能会对速度产生真正的影响.

Actually, it may be also a performance problem. My file has a really big number of items (up to billions) so doing so many 'is/as' tests may actually have a real impact on speed.

推荐答案

你做错了.

您需要更改代码,以便在您知道需要的类型之前不会创建容器,然后创建正确的类型:

You need to change your code so that the container is not created until you know what type it needs to be, and then create the proper type:

Procedure Main;
begin

 if FileType= Circle then
   Viewer.Container := TCircle.Create
 else
  Viewer.Container := TTriangle.Create;

 Viewer.Container.Load(FileName);

 Caption := IntToStr(Viewer.Container.NoOfItems);  <---- it calls proper code
end;

这是一个为您使用继承和多态的工作示例:

Here's a working example of using inheritance and polymorphism for you:

program InheritancePolymorphismTest;

uses
  System.SysUtils;

type
  TAnimal=class
  public
    procedure Sit; virtual;
    procedure Speak; virtual;
  end;

  TDog=class(TAnimal)
  public
    procedure Sit; override;
    procedure Speak; override;
  end;

  TCat=class(TAnimal)
  public
    procedure Speak; override;
  end;

  TAnimalArray = array of TAnimal;

{ TCat }

procedure TCat.Speak;
begin
  inherited;
  WriteLn('Bah! No way cats speak when told.');
end;

{ TDog }

procedure TDog.Sit;
begin
  inherited;
  WriteLn('Sitting down.');
end;

procedure TDog.Speak;
begin
  inherited;
  Writeln('Woof! Woof!');
end;

procedure TAnimal.Sit;
begin

end;

procedure TAnimal.Speak;
begin

end;


var
  Animals: TAnimalArray;
  i: Integer;
  Pet: TAnimal;
{ TAnimal }

const
  NumAnimals = 5;


begin
  SetLength(Animals, NumAnimals);
  for i := 0 to High(Animals) do
  begin
    if Odd(i) then
      Animals[i] := TDog.Create
    else
      Animals[i] := TCat.Create;
  end;

  for Pet in Animals do
  begin
    Pet.Speak;
    Pet.Sit;
  end;

  Writeln('');
  Readln;
end.

这篇关于继承/多态概念的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-27 19:29