我的一位同事和我一直在讨论如何在函数中声明变量。
假设你有一个名为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;
答案 0 :(得分:1)
它是一个TStringList,因此您还应将其声明为TStringList(第一个示例)。其他所有内容都会让您或其他人稍后阅读这些代码。
答案 1 :(得分:0)
我的投票是第二种形式 - 想法是TStrings定义合同/接口,并且更好地为它们编码。
答案 2 :(得分:0)
我会说这取决于你是否期望TStringList是否可以改为实现TStrings的其他东西。如果您不希望它发生更改,请使用TStringList并访问仅在TStringList中的特殊功能(猜测不是这种情况)。如果您希望它可能会发生变化,请将其声明为TStrings并坚持使用“安全”方法。
在这个具体案例中我会说没关系。天啊,你可能会改变变量声明,但无论如何都不会改变。因此,请使用您最喜欢的方式 - 这是一个偏好问题。
答案 3 :(得分:0)
我同意Schnaader。
TStringList具有更多属性和方法,即TStrings(它是一个抽象类)。使用TStrings变量禁止使用这些成员unles使用强制转换。但是,我认为这会使事情变得更糟。
您可以在函数参数中使用TStrings。
procedure TMyClass.MyMethod(const AList: TStrings);
begin
end;
或作为财产。但是,如果局部变量和字段的真实类型被标记,那么它们就会更加通用。
答案 4 :(得分:0)
这取决于......
在Java中,我经常看到使用可用的最高抽象级别进行声明的建议,尽管它通常适用于接口。
例如:
Collection list = new ArrayList();
[loop] list.add(someItem); [end loop]
等。
为什么?它允许更改实现(在某些情况下的细节:某些实现更适合某些用法(队列,链表,堆栈......),因此它可能主要是速度/内存问题)通过最小化更改的影响。
当然,如果您使用特定于实现的方法,则必须在声明中更具体。
另一个优点:当一个方法需要一个Collection参数时,只要它只需要使用泛型方法,它就可以处理更广泛的输入。