Pregunta

Un colega mío y yo hemos estado discutiendo cómo declarar variables en una función.

Digamos que tiene una clase llamada TStrings (que usa Delphi por razones de explicación) que tiene al menos un método abstracto y una clase descendiente llamada TStringList que obviamente implementa el método abstracto, pero no introduce nada más que no necesite. ya implementado en el ancestro, ¿cómo declararía una variable de función de tipo TStringList?

Aquí hay dos ejemplos. ¿Cuál se considera mejor práctica y por qué?

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;
¿Fue útil?

Solución

Es una TStringList, por lo que también debe declararla como TStringList (primer ejemplo). Todo lo demás podría confundirlo a usted u otras personas que lean el código más tarde.

Otros consejos

Mi voto es la segunda forma: la idea es que TStrings define un contrato / interfaz y es mejor codificarlos.

Yo diría que depende de si espera si TStringList podría cambiarse a otra cosa que implemente TStrings o no. Si no espera que cambie, use TStringList y obtenga acceso a funciones especiales que están solo en TStringList (supongo que este no es el caso). Si espera que pueda cambiar, declare como TStrings y manténgase en & Quot; safe & Quot; métodos.

En este caso específico, diría que no importa. Demonios, probablemente podrías cambiar la declaración de variable y nada cambiaría de todos modos. Así que usa el que más te guste: es una cuestión de preferencia.

Estoy de acuerdo con Schnaader.

TStringList tiene más propiedades y métodos que TStrings (que es una clase abstracta). El uso de la variable TStrings prohíbe el uso de estos miembros a menos que esté utilizando conversiones. Pero eso está empeorando las cosas en mi opinión.

Puede usar TStrings en un argumento de función.

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

O como una propiedad. Pero las variables y los campos locales son más versátiles si se descomponen en su tipo real.

Depende ...

En Java, a menudo vi la recomendación de hacer declaraciones utilizando el nivel de abstracción más alto que se pueda usar, aunque generalmente se aplica a las interfaces.

Por ejemplo:

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

etc.
¿Por qué? Permite cambiar la implementación (un detalle en algunos casos: algunas implementaciones se adaptan mejor a algunos usos (cola, lista enlazada, pila ...), por lo que podría ser principalmente un problema de velocidad / memoria) al minimizar el impacto del cambio.

Por supuesto, si usa métodos específicos para una implementación, debe ser más específico en la declaración.

Otra ventaja: cuando un método espera un parámetro de Colección, puede funcionar en un rango de entrada más amplio siempre que necesite usar solo métodos genéricos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top