首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在方法之前或之后有数据字段的约定吗?(在类、对象或记录中)

在方法之前或之后有数据字段的约定吗?(在类、对象或记录中)
EN

Stack Overflow用户
提问于 2013-03-04 00:50:56
回答 2查看 519关注 0票数 1

当您定义一个类(或使用方法的对象或记录)时,我只是想知道是否有任何关于数据字段是否应该出现在方法字段之前的约定?

我的意思是,在下面的小例子中,这两种情况的区别。(编辑以使具体问题更清楚)

代码语言:javascript
复制
type TWhatever = Object
      private
        a,b : Integer;
      public
        procedure SetWhatever(x,y :Integer);
        procedure ShowWhatever;
      end;

对比

代码语言:javascript
复制
type TWhatever = Object
      public
        procedure SetWhatever(x,y :Integer);
        procedure ShowWhatever
      private
        a,b : Integer;
     end;

我一直使用先列出数据字段的惯例,但老实说,我并不认为这有什么不同。然而,最近我遇到了一些代码,除非首先列出数据字段,否则它们无法工作(不会编译)。

我在这里记录了这个案例:Delphi 2006不允许记录方法中记录类型的const参数?

总结是,如果将数据字段放在方法之后,那么如果对象有任何方法试图将给定对象作为"const“参数传递,则代码将不会编译。例如,这样的东西不会编译:

代码语言:javascript
复制
procedure TWhatever.SomeMethod( const : w1: TWhatever);

显然它会在Delphi的后期版本上编译,但是我已经在Delphi7和Delphi2006上测试过了,而且也不会在任何一个版本上编译。

只有在执行所有三种操作(数据字段最后,将对象作为方法中的参数传递,对此参数使用const关键字)时,才会出现问题。因此,您可以通过从参数中删除const关键字或将数据字段放在方法前面来解决这个问题。

总之,这件事让我想知道这里是否有一个会议要遵循呢?

编辑我添加了这个以给出一个特定的代码示例

以下程序无法在D7和D2006上编译:

代码语言:javascript
复制
program bugtest;
{$APPTYPE CONSOLE}
uses SysUtils;

type Tob = object
   public
    procedure setOb(const a,b: integer);
    procedure addToOb(const ob1: Tob);
    procedure printOb;
   private
    x,y : Integer;
   end;

procedure Tob.setOb(const a,b: integer);
begin
  x:=a; y:=b;
end;

procedure Tob.addToOb(const ob1: Tob);
begin
  x:=x+ob1.x; y:= y+ob1.y;
end;

procedure Tob.printOb;
begin
  writeln(x,' ',y);
end;

var r1,r2: Tob;
begin
  r1.setOb(2,3);
  r2.setOb(10,100);
  r1.addToOb(r2);
  r1.printOb;
  r2.printOb;
  readln;
end.

以下程序在D7和D2006上都完美地编译和运行:

代码语言:javascript
复制
program bugtest;
{$APPTYPE CONSOLE}
uses SysUtils;

type Tob = object
   private
    x,y : Integer;
   public
    procedure setOb(const a,b: integer);
    procedure addToOb(const ob1: Tob);
    procedure printOb;
   end;

procedure Tob.setOb(const a,b: integer);
begin
  x:=a; y:=b;
end;

procedure Tob.addToOb(const ob1: Tob);
begin
  x:=x+ob1.x; y:= y+ob1.y;
end;

procedure Tob.printOb;
begin
  writeln(x,' ',y);
end;

var r1,r2: Tob;
begin
  r1.setOb(2,3);
  r2.setOb(10,100);
  r1.addToOb(r2);
  r1.printOb;
  r2.printOb;
  readln;
end.

Delphi 7版本是:Delphi个人版本7.0构建4.453

D2006版本是:。版本10.0.2288.42451,Update2

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-04 09:16:48

我认为公平地说,有一个广泛使用的公约。通常,类声明的排列方式如下:

代码语言:javascript
复制
TMyClass = class
  // published declarations, managed by form designer
  Component1: TMyComponent;
  procedure MyEventHandler(Sender: TObject);
private
  FMyPrivateField: Integer;
  procedure MyPrivateMethod;
protected
  FMyProtectedField: Integer;
  procedure MyProtectedMethod;
public
  FMyPublicField: Integer;
  procedure MyPublicMethod;
published
  FMyPublishedField: Integer;
  procedure MyPublishedMethod;
end;

换句话说,这些部分将首先使用表单设计器的声明来组织,然后按照增加可见性的顺序排列。

有趣的是,其他公约在其他语言中使用。例如,看看谷歌C++风格指南,其中节的顺序与上面的顺序相反。

就我个人而言,我宁愿先看到公开声明。当读取已经存在的代码时,我通常使用自顶向下的透视图进行阅读。在编写代码时,我常常发现自上而下的方法是有益的.

查看我的TComplex记录,有一个原因可以解释为什么声明是按原样排序的。我有一些类似的记录,其中有些是不同的记录。例如:

代码语言:javascript
复制
type
  TVector = record
  public
    class operator Negative(const V: TVector): TVector;
    class operator Equal(const V1, V2: TVector): Boolean;
    class operator NotEqual(const V1, V2: TVector): Boolean;
    class operator Add(const V1, V2: TVector): TVector;
    class operator Subtract(const V1, V2: TVector): TVector;
    class operator Multiply(const V: TVector; const D: Double): TVector;
    class operator Multiply(const D: Double; const V: TVector): TVector;
    class operator Divide(const V: TVector; const D: Double): TVector;
    function IsZero: Boolean;
    function IsNonZero: Boolean;
    function IsUnit: Boolean;
    function Max: Double;
    function Sum: Double;
    function Mag: Double;
    function SqrMag: Double;
    function MagNormalComponent: Double;
    procedure MakeAxisymmetric;
    class function SNaN: TVector; static;
    function GetHashCode: Integer; inline;
  public
    case Boolean of
    False:
      (X, Y, Z: Double);
    True:
      (a: array [1..3] of Double);
  end;

现在,记录的变体部分必须出现在最后。否则就会产生编译错误。所以这张唱片是没有选择的。在为TVector和相关记录建立了惯例之后,TComplex就这样做了。

票数 1
EN

Stack Overflow用户

发布于 2013-03-04 01:02:18

根据编译器,字段声明位于任何 类部分中的任何方法声明之前。类上可能有任意数量的节,即使具有相同的可见性。

例如:

代码语言:javascript
复制
type
  TMyObject = class
  private
    FTest: Integer;
    procedure A();
  private
    FOtherTest: Integer;
    procedure B();
  end;

编译,您可以争论FOtherTest是否在procedure A()之后。

由于这是由编译器强制执行的,所以没有办法将其改为其他方式,所以我不确定是否将其称为约定,但必须是这样。

另一方面,

代码语言:javascript
复制
type
  TMyObject = class
  private
    procedure A();
    FTest: Integer;
  end;

没有编译,有以下错误:

方法或属性之后不允许E2169字段定义

如果将它作为任何类型的参数传递,都不重要。根据我的经验,如果您只是在方法之后声明任何字段,则会出现错误。

编辑

在对问题进行编辑后,OP表示,如果对象作为const参数传递给例程,则在Delphi 7或2006中,如果字段在具有方法的区段中声明,则该对象不会在Delphi 7或2006中编译。

我设法在VM中运行了非常旧的D7,这个示例编译OK:

它使用objectclass声明进行编译,而且由于records不支持该版本上的方法,显然记录声明不会编译。

Edit2

它还编译对象是否作为const参数传递给方法(无论是同一对象的方法还是其他方法)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15192866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档