Как объявить переменные - PullRequest
1 голос
/ 09 декабря 2008

Мой коллега и я обсуждали, как объявлять переменные в функции.

Допустим, у вас есть класс с именем 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;

Ответы [ 5 ]

1 голос
/ 09 декабря 2008

Это TStringList, поэтому вы должны также объявить его как TStringList (первый пример). Все остальное может запутать вас или других, кто читает код позже.

0 голосов
/ 09 декабря 2008

Это зависит ...

В Java я часто видел рекомендации делать объявления, используя самый высокий уровень абстракции, который можно использовать, хотя это обычно относится к интерфейсам.

Например:

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

и т.д.
Зачем? Это позволяет изменить реализацию (деталь в некоторых случаях: некоторые реализации лучше подходят для некоторых применений (очередь, связанный список, стек ...), так что это может быть связано главным образом со скоростью / памятью), сводя к минимуму влияние изменений.

Конечно, если вы используете методы, специфичные для реализации, вы должны быть более конкретны в объявлении.

Еще одно преимущество: когда метод ожидает параметр Collection, он может работать с более широким диапазоном ввода, если ему нужно использовать только общие методы.

0 голосов
/ 09 декабря 2008

Я согласен со Schnaader.

TStringList имеет больше свойств и методов, чем TStrings (который является абстрактным классом). Использование переменной TStrings запрещает использование этих членов, если вы используете приведение типов. Но, на мой взгляд, это еще хуже.

Вы можете использовать TStrings в аргументе функции.

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

Или как собственность. Но локальные переменные и поля более универсальны, если они декалярированы, их реальный тип.

0 голосов
/ 09 декабря 2008

Я бы сказал, что это зависит от того, ожидаете ли вы, что TStringList может быть изменен на что-то другое, реализующее TStrings или нет. Если вы не ожидаете, что он изменится, используйте TStringList и получите доступ к специальным функциям, которые есть только в TStringList (угадайте, что это не так). Если вы ожидаете, что это может измениться, объявите его как TStrings и придерживайтесь «безопасных» методов.

В этом конкретном случае я бы сказал, что это не имеет значения. Черт, вы, вероятно, могли бы изменить объявление переменной, и все равно ничего бы не изменилось. Поэтому используйте то, что вам больше нравится - это вопрос предпочтений.

0 голосов
/ 09 декабря 2008

Мой голос - это вторая форма - идея в том, что TStrings определяет контракт / интерфейс и лучше кодировать их.

...