【问题标题】:Defining method body inside class declaration?在类声明中定义方法体?
【发布时间】:2015-08-20 03:06:03
【问题描述】:

我正在尝试在 Free Pascal 中的类声明中定义所有类方法,但我无法在网上找到任何示例。目前我必须这样做:

unit Characters;

{$mode objfpc}{$H+}

// Public
interface
type
  TCharacter = class(TOBject)
    private
      FHealth, FAttack, FDefence: Integer;
      procedure SetHealth(newValue: Integer);
    public
      constructor Create(); virtual;
      procedure SayShrek();
      function GetHealth(): Integer;
    published
      property Health: Integer read GetHealth write SetHealth;
    end;


// Private
implementation
    constructor TCharacter.Create;
  begin
    WriteLn('Ogres have LAYERS!');
    end;

  procedure TCharacter.SayShrek;
  begin
    WriteLn('Shrek!');
    end;

  procedure TCharacter.SetHealth(newValue: Integer);
  begin
    FHealth:= FHealth + newValue;
    end;

  function TCharacter.GetHealth() : Integer;
  begin
    GetHealth:= FHealth;
  end;

end.

有没有什么办法可以让这更干净一点?在别处定义所有内容看起来很杂乱无章。

编辑:

为了澄清,我想按照以下方式做一些事情:

TMyClass = class(TObject)
    public
      procedure SayHi();
      begin
          WriteLn('Hello!');
      end;
end;

而不必进一步定义它。这可能吗?

【问题讨论】:

    标签: pascal lazarus freepascal delphi


    【解决方案1】:

    这在 Pascal 中是不可能的。只是它的语法不允许这样做。

    Pascal 的基本设计是将单元划分为interface可以做什么?)和implementation怎么做?) . 编译器在解析implementation 部分之前读取所有interface 部分。您可能从 C 语言中知道这一点。 implementation 可以描述为 *.c 文件,而 interface 相当于 C 中的 *.h 文件。

    此外,此类代码会严重降低 interface 部分(f.i. 类声明)的可读性。

    您希望从中获得什么好处?

    【讨论】:

    • 啊,好的。 C 的解释帮助很大。非常感谢您的帮助!
    【解决方案2】:

    不,你不能这样做。 Pascal 有一个单遍编译器从一开始就是为单遍编译而设计的,所以在声明之前你不能使用它。

    作为一个简单的伪代码示例:

    MyClass = class
      procedure MethodA;
      begin
        MethodB; <== At this point the compiler knows nothing about MethodB
      end;
      procedure MethodB;
      begin
      end;
    end;
    

    这就是为什么每个单元至少有两个部分:interface(声明,您可以将其视为关于 C++ 头文件)和implementation

    但是,在实现循环声明的语言语法中有一些技巧,您可以使用前向声明。

    对于指针:

    PMyRec = ^TMyRec; // Here is TMyRec is not declared yet but compiler can to handle this
    TMyRec = record
      NextItem: PMyRec;
    end;
    

    对于课程:

    MyClassA = class; // Forward declaration, class will be fully declared later
    
    MyClassB = class
      SomeField: MyClassA;
    end;
    
    MyClassA = class
      AnotherField: MyClassB;
    end;
    

    在 IDE 中,您可以使用 Shift+Ctrl+Up/Down 键在项目的声明和实现之间导航。

    【讨论】:

    • 我希望做更多类似的事情:MyClassA = 类过程测试;开始 WriteLn('测试');结尾;结尾;那可能吗?看起来您在第一个示例中确实有方法体,即使它引用了尚未定义的内容。
    • 使用前定义是一种哲学。编译器和遍数各不相同。我认为 FPC 大约有 5-6 次传球。错误生成例如这种方式好多了。
    • @MarcovandeVoort 谢谢。很多年前我似乎错过了一些东西:) 答案已更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多