【问题标题】:Abstraction in DelphiDelphi中的抽象
【发布时间】:2009-07-15 10:38:31
【问题描述】:

如果我有子类,子类继承父类的所有方法,但是如何在父类中使用子类的函数呢?这就是抽象吗?如何实现?

我的代码:

type
cParent = class(TObject)
private
  function ParentFunction:byte;
  function ChildFunction:byte;virtual;abstract;
end;

type
cChild = class(cParent)
private function ChildFunction:byte;override;
end;

function cChild.ChildFunction:byte;
begin
  Exit(20);
end;

function cParent.ParentFunction:byte;
begin
  Exit(10);
end;

var
c:cParent;

begin
  c:= cParent.Create;
  WriteLn(c.ChildFunction);
  Readln;
end.

它编译文件,但我得到抽象异常。

【问题讨论】:

  • 当你说它编译良好时,你真的是说你没有从编译器那里得到警告,告诉你你正在实例化一个抽象类吗?您需要更加努力地消除编译器提示和警告,而不仅仅是错误。
  • 关于传统风格的简单介绍。在 Delphi 中,通常在类(和其他类型)名称前加上 T,而不是 c。函数的返回值通常通过将隐式 Result 变量设置为一个值来设置,而不是使用 Exit,即 Result := 10;,而不是 Exit(10);。 Exit 语法是 D2009 才添加的 注意:你也可以使用函数名,而不是结果(ParentFunction := 10;) - 效果是一样的,它是原始的 Pascal 语法

标签: delphi class


【解决方案1】:
c:= cParent.Create;
WriteLn(c.ChildFunction);

您在这里创建一个 cParent 类的实例。这个类只包含一个可以被其他类覆盖的抽象 ChildFunction。该函数未在 cParent 中实现,因此您会得到一个抽象错误。

如果您改用实现 ChildFunction 的 cChild 类,则代码可以工作:

c:= cChild.Create;
WriteLn(c.ChildFunction);

为了清楚起见,假设一个名为GeometricObject 的父类具有一个虚拟抽象方法CalculateVolume。您现在可以使用球体/框的公式创建实现CalculateVolume 的子类,如SphereObjectBoxObject。但是创建GeometricObject的实例并调用CalculateVolume是没有意义的。

【讨论】:

  • 好的,但是“virtual”、“abstract”和“override”关键字有什么用呢?
  • "virtual" 表示该方法可以被子类覆盖。 “抽象”表示该方法不是由父类实现的,但可以在子类中实现。 “覆盖”,嗯,覆盖父类的虚拟方法。所有抽象方法都必须是虚拟的,但方法可以是虚拟的而不是抽象的。
  • 抽象方法是 C++ 所指的“纯虚拟”方法。它们必须在子类中实现。
【解决方案2】:

您创建了 cParent 类的实例。此类没有 childFunction 的实现。 c 必须是 cChild 类的实例。 正确代码: c := cChild.Create; WriteLn(c.ChildFunction);

【讨论】:

    【解决方案3】:

    使用子类创建实例:

    c:= cChild.Create;
    

    【讨论】:

      【解决方案4】:

      在我看来,您混淆了继承关系和所有格关系。如果您将“cChild”类定义为从“cParent”类继承,则“cChild”类“cParent”,这并不意味着“Parent”类可以访问任何子类类。您可以在“cParent”类中调用抽象函数“ChildFunction”的唯一方法是来自另一个函数,例如“ParentFunction”,但前提是对象本身不是“cParent”:

      function cParent.ParentFunction:byte;
      begin
        Result := ChildFunction * 2;
      end;
      
      var
        c:cParent;
      
      begin
        c:= cChild.Create;
        WriteLn(c.ParentFunction);
        Readln;
      end.
      

      这里,由于c是一个cChild,ParentFunction正确调用了在cChild中定义的ChildFunction。

      【讨论】:

        【解决方案5】:

        针对 schnaader,关于 CS 101:

        “虚拟”意味着该方法可以被子类覆盖。

        不仅如此,非虚函数也可以很高兴地被子类覆盖。区别很重要:当父类调用虚函数时,会执行CHILD函数。这允许子类实现将由父类调用的函数,而父类不知道它们的任何信息。这就是多态性的本质。

        【讨论】:

          猜你喜欢
          • 2011-09-05
          • 2017-06-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-23
          • 1970-01-01
          • 1970-01-01
          • 2012-09-16
          相关资源
          最近更新 更多