1

我和我的一位同事一直在讨论如何在函数中声明变量。

假设你有一个名为 TStrings 的类(为了解释而使用 Delphi),它至少有一个抽象方法和一个名为 TStringList 的后代类,它显然实现了抽象方法,但它没有引入任何你需要的尚未实现的东西祖先,您将如何声明 TStringList 类型的函数变量?

这里有两个例子。哪个被认为是更好的做法,为什么?

procedure AddElements;
var
  aList: TStringList;
begin
  aList := TStringList.Create;
  try
    aList.Add('Apple');
    aList.Add('Pear');
  finally
    aList.free;
  end;
end;

procedure AddElementsII;
var
  aList: TStrings;
begin
  aList := TStringList.Create;
  try
    aList.Add('Apple');
    aList.Add('Pear');
  finally
    aList.free;
  end;
end;
4

5 回答 5

1

它是一个 TStringList,因此您还应该将其声明为 TStringList(第一个示例)。其他一切都可能使您或其他稍后阅读代码的人感到困惑。

于 2008-12-09T11:16:51.477 回答
0

我的投票是第二种形式 - 想法是 TStrings 定义了一个合同/接口,并且更好地为它们编码。

于 2008-12-09T11:16:33.817 回答
0

我想说这取决于您是否期望 TStringList 可能会更改为其他实现 TStrings 的东西。如果您不希望它发生变化,请使用 TStringList 并访问仅在 TStringList 中的特殊功能(猜想情况并非如此)。如果您期望它可能会更改,请将其声明为 TStrings 并坚持使用“安全”方法。

在这种特定情况下,我会说没关系。地狱,您可能会更改变量声明,但无论如何都不会改变。所以使用你最喜欢的——这是一个偏好问题。

于 2008-12-09T11:26:00.367 回答
0

我同意施奈德的观点。

TStringList 比 TStrings(它是一个抽象类)具有更多的属性和方法。除非您使用强制转换,否则使用 TStrings 变量会禁止使用这些成员。但在我看来,这让事情变得更糟。

您可以在函数参数中使用 TStrings。

procedure TMyClass.MyMethod(const AList: TStrings);
begin
end;

或者作为财产。但是,如果将局部变量和字段声明为真实类型,则它们会更加通用。

于 2008-12-09T11:32:51.693 回答
0

这取决于...

在 Java 中,我经常看到使用可用的最高抽象级别进行声明的建议,尽管它通常适用于接口。

例如:

Collection list = new ArrayList();
[loop] list.add(someItem); [end loop]

等等
为什么?它允许通过最小化更改的影响来更改实现(在某些情况下是一个细节:某些实现更适合某些用途(队列、链表、堆栈......),因此它可能主要是速度/内存问题)。

当然,如果您使用特定于实现的方法,则必须在声明中更加具体。

另一个优点:当一个方法需要一个 Collection 参数时,只要它只需要使用泛型方法,它就可以处理更广泛的输入。

于 2008-12-09T14:06:22.320 回答