当您定义一个类(或使用方法的对象或记录)时,我只是想知道是否有任何关于数据字段是否应该出现在方法字段之前的约定?
我的意思是,在下面的小例子中,这两种情况的区别。(编辑以使具体问题更清楚)
type TWhatever = Object
private
a,b : Integer;
public
procedure SetWhatever(x,y :Integer);
procedure ShowWhatever;
end;对比
type TWhatever = Object
public
procedure SetWhatever(x,y :Integer);
procedure ShowWhatever
private
a,b : Integer;
end;我一直使用先列出数据字段的惯例,但老实说,我并不认为这有什么不同。然而,最近我遇到了一些代码,除非首先列出数据字段,否则它们无法工作(不会编译)。
我在这里记录了这个案例:Delphi 2006不允许记录方法中记录类型的const参数?
总结是,如果将数据字段放在方法之后,那么如果对象有任何方法试图将给定对象作为"const“参数传递,则代码将不会编译。例如,这样的东西不会编译:
procedure TWhatever.SomeMethod( const : w1: TWhatever);显然它会在Delphi的后期版本上编译,但是我已经在Delphi7和Delphi2006上测试过了,而且也不会在任何一个版本上编译。
只有在执行所有三种操作(数据字段最后,将对象作为方法中的参数传递,对此参数使用const关键字)时,才会出现问题。因此,您可以通过从参数中删除const关键字或将数据字段放在方法前面来解决这个问题。
总之,这件事让我想知道这里是否有一个会议要遵循呢?
编辑我添加了这个以给出一个特定的代码示例
以下程序无法在D7和D2006上编译:
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上都完美地编译和运行:
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。

发布于 2013-03-04 09:16:48
我认为公平地说,有一个广泛使用的公约。通常,类声明的排列方式如下:
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记录,有一个原因可以解释为什么声明是按原样排序的。我有一些类似的记录,其中有些是不同的记录。例如:
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就这样做了。
发布于 2013-03-04 01:02:18
根据编译器,字段声明位于任何 类部分中的任何方法声明之前。类上可能有任意数量的节,即使具有相同的可见性。
例如:
type
TMyObject = class
private
FTest: Integer;
procedure A();
private
FOtherTest: Integer;
procedure B();
end;编译,您可以争论FOtherTest是否在procedure A()之后。
由于这是由编译器强制执行的,所以没有办法将其改为其他方式,所以我不确定是否将其称为约定,但必须是这样。
另一方面,
type
TMyObject = class
private
procedure A();
FTest: Integer;
end;没有编译,有以下错误:
方法或属性之后不允许E2169字段定义
如果将它作为任何类型的参数传递,都不重要。根据我的经验,如果您只是在方法之后声明任何字段,则会出现错误。
编辑
在对问题进行编辑后,OP表示,如果对象作为const参数传递给例程,则在Delphi 7或2006中,如果字段在具有方法的区段中声明,则该对象不会在Delphi 7或2006中编译。
我设法在VM中运行了非常旧的D7,这个示例编译OK:

它使用object或class声明进行编译,而且由于records不支持该版本上的方法,显然记录声明不会编译。
Edit2
它还编译对象是否作为const参数传递给方法(无论是同一对象的方法还是其他方法)。

https://stackoverflow.com/questions/15192866
复制相似问题