Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 遗传/多态概念_Delphi_Oop - Fatal编程技术网

Delphi 遗传/多态概念

Delphi 遗传/多态概念,delphi,oop,Delphi,Oop,我有两个二进制文件,其中包含类似类型的数据,因此我想为这两个文件创建一个统一的查看器TViewer。 对于这两种文件类型,有些方法是通用的,有些则不是。所以我创建了一个基类 t形状,以及从中导出的t圆形和t三角形 伪代码: TShape = class(TObject) function NoOfItems: integer; virtual; abstract; end; TCircle = class(TShape) function NoOfItems: integer; ov

我有两个二进制文件,其中包含类似类型的数据,因此我想为这两个文件创建一个统一的查看器TViewer。 对于这两种文件类型,有些方法是通用的,有些则不是。所以我创建了一个基类 t形状,以及从中导出的t圆形和t三角形

伪代码:

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;
Caption:= Viewer.Container.NoOfItems;
显然,使用is并没有什么错,只是我将不得不在任何地方附近的许多地方使用它。有更好的方法来实现这个统一的查看器吗

更新:
实际上,这可能也是一个性能问题。我的文件中有大量的项,多达数十亿项,因此执行如此多的“是/是”测试实际上可能会对速度产生真正的影响。

真正的代码和真正的输出。多态性仍然有效! 因此,我认为您在声明和实现类层次结构时遗漏了一些重要的细节

type
TShape = class(TObject)
  function IAm: string; virtual; abstract;
end;

TCircle = class(TShape)
  function IAm: string; override;
end;

TTriangle = class(TShape)
  function IAm: string; override;
end;


{ TCircle }

function TCircle.IAm: string;
begin
  Result := 'I am circle'
end;

{ TTriangle }

function TTriangle.IAm: string;
begin
  Result := 'I am triangle'
end;


procedure TForm1.Button6Click(Sender: TObject);
var
  Shape: TShape;
begin
  Shape := TCircle.Create;
  Memo1.Lines.Add(Shape.IAm);
  Shape.Free;
  Shape := TTriangle.Create;
  Memo1.Lines.Add(Shape.IAm);
  Shape.Free;
end;

output
  I am circle
  I am triangle
你做错了


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

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;

当然,您可以使用IntVar:=Viewer.Container.NoOfItems;-这是典型的多态性用法,您根本不必对其进行类型转换,也不必对示例中的代码进行类型转换,这意味着这很可能不是您真正的代码。实际上,这不可能是您真正的代码,因为您已将NoOfItems声明为返回整数的函数,但您直接将其分配给标题。如果需要帮助,请发布真实代码。@MBo-它将调用TShape的方法。什么都不做是抽象的。@KenWhite-是的。这不是真正的代码。真正的代码是大到可以张贴在这里。我将尝试制作一个小的可编译演示。无论如何,Viewer.Container.NoOfItems调用TShape的方法,该方法不返回任何内容!好啊我在表格中加了摘要。现在很明显,Viewer.Container.NoOfItems失败了。在您知道它需要什么类型之前,容器不会被创建。。。正当明显地我不知道我是怎么搞砸的。非常感谢+1并接受。我将考虑使用工厂模式来决定创建什么。如果FillType=圆形,则。。。有点臭。@Andy_D:问题不在于使用什么设计模式。这就是为什么继承和多态性不能在这里工作?这就是我的答案。不过,感谢您的意见:-我知道@KenWhite,我只是观察到工厂模式将使解决方案更加灵活和可读
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;
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.