Вопрос

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

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

Решение

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

Другие советы

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

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

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

Я согласен со Шнадером.

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

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

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

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

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

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

Например:

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top