为什么Delphi编译器在类方法使用self时不会抛出警告?

4
在我的工作场所,我们有一些代码,其中class function引用Self,实际上创建了一个潜在的访问冲突,如果对象没有被初始化。在类方法中,Self的含义是否会改变,以便引用类而不是对象?
我认为这个代码之所以能够工作,是因为Self指的是另一个class function而不是常规方法。
我创建了以下测试类:
constructor TTest.Create;
begin
  FTest := 'Hej';
end;

procedure TTest.GoTest;
begin
  ShowMessage(FTest);
end;

class procedure TTest.Test;
begin
  Self.GoTest;
end;

然而,编译此代码会抛出一个错误:
[dcc32 Error] Unit1.pas(51): E2076 This form of method call only allowed for class methods or constructor

我还尝试直接引用FTest进行测试,但是出现了另一个错误:

[dcc32 Error] Unit1.pas(51): E2124 Instance member 'FTest' inaccessible here

我想知道,在类方法中是否存在可能导致Self不安全的情况。

我知道,引用全局对象并假设它们一直存在是不好的。


走一遍代码,设置一个断点,看看此时的“self.name”是什么。我不太喜欢过多使用self,因为它取决于上下文中self的含义。 - Pieter B
也许 Delphi 应该提示 Self 可能会引起混淆,或者如果该方法移动到另一个类中,可能会改变其含义。 - Svip
如果有提示,应该很容易地被抑制。我不想每次使用Self时都有提示。 - Arioch 'The
我怀疑我们无法让 Delphi 提示关于 Delphi 的非习惯用法。因为正如已经被接受的答案所描述的那样,类方法中的 Self 有其作用的场景。 - Svip
1个回答

6
在类方法中,Self指的是类本身而不是对象。文档documentation中说到:
在定义类方法时,标识符Self表示调用该方法的类(可以是定义它的类的后代)。如果在类C中调用该方法,则Self的类型为C类的类型。因此,您不能使用Self访问实例字段、实例属性和普通(对象)方法。您可以使用Self调用构造函数和其他类方法,或者访问类属性和类字段。
类方法可以通过类引用或对象引用调用。当通过对象引用调用时,对象的类成为Self的值。
编译器不会反对您使用Self,因为这是一种合法且受支持的做法。只有在尝试使用实例成员、实例方法等时,它才会发出警告。

Self在类方法中具有与实例方法相同的含义,原因也是一样的。它允许您完全指定一个符号,从而避免作用域歧义。更重要的是,它允许您访问调用该方法的实际类。这可能是定义该方法的类的后代。

然而,我想知道是否可能存在Self在类方法中潜在的危险情况。

我没有看到语言本身的任何特定危险。事实上,使用Self可以减小作用域,从而减少无意中引用局部变量而不是类成员的危险。


在类方法中使用 Self 是 Delphi 中惯用的写法吗? - Svip
不是真的。通常你会像实例方法一样省略它。如果你需要使用它,因为你有一个变量作用域冲突,那么你可能需要考虑重命名冲突的局部变量或类成员之一。 - David Heffernan
好的,谢谢,这就是我需要知道的!幸运的是,删除这些Self实例应该相当容易。 - Svip
我会说这是惯用法。在Java和C++中,您不能在类(静态)方法中使用this - Leonardo Herrera
2
@LeonardoHerrera,这不是惯用语的意思。你可以说在C++中,在比较表达式中将常量放在左边是惯用的(以防止写=时实际上是==),但在Delphi中却不是,尽管你可以这样做。换句话说,惯用语并不是关于语言中可能性的问题,而更多地涉及到大多数程序员如何表达事物。 - Ian Goldby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接