delphi - Agregar una unidad a la interfaz usa una cláusula en lugar de la cláusula de uso de Implementación
uses-clause (5)
El IDE también usa cómo usted declara sus usos para determinar lo que necesita compilar.
Si su sección de interfaz usa UnitA y su sección de implementación usa UnitB, entonces, si la unidad B necesita recompilar, su unidad no lo hará, pero si la unidad A cambia, entonces su unidad necesitará ser recompilada.
Es uno de los secretos de la velocidad de compilación súper rápida de Delphis.
En cuanto a su ejecutable terminado, espero que tenga el mismo tamaño donde quiera que coloque las declaraciones (el enlazador es inteligente y solo enlaces en métodos, etc. que realmente usa su aplicación), pero la ubicación real de varias fuentes haría casi sin duda cambiará si se cambia el orden de las declaraciones de la unidad.
Cuando uso Delphi: si tengo una unidad que está llena de constantes como ...
Unit AConsts;
Interface
Const
Const1 : WideString = ''Const1'';
Const2 : WideString = ''Const2'';
Const3 : WideString = ''Const3'';
Const4 = 100;
Const5 = 100;
Implementation
end.
y quiero usar esta unidad desde otra unidad, ¿hay alguna diferencia entre ...
Unit AUnit;
Interface
Uses
AConsts;
Implementation
end.
y
Unit AUnit;
Interface
Implementation
Uses
AConsts;
end.
? O en otras palabras, ¿hay alguna diferencia entre los dos en lo que respecta a una aplicación compilada?
[Editar 1]
Gracias por las respuestas hasta ahora.
No hice esta pregunta lo suficientemente clara, y por eso me disculpo. La pregunta no es sobre el alcance, evitar referencias circulares, etc. Se trata de diferencias en la aplicación compilada. Tal vez otro ejemplo ayudaría.
Si UnitA, UnitB y UnitC usan AConsts, habría una diferencia en la aplicación compilada (suponiendo que no haya conflictos de nombres entre las constantes en las unidades AConsts y otro código) entre App1 donde estas UnitA, UnitB y UnitC tienen todos aconsts en la interfaz cláusula de usos de la sección y App2 donde UnitA, UnitB y UnitC tienen elementos en la cláusula de usos de la sección Implementación.
La diferencia tiene que ver con dónde se le permite referirse a las cosas que AConsts
tiene en su sección de interfaz. En el primer AUnit
, puede usar Const4
para declarar un conjunto de tamaño fijo en esa sección de interfaz. No podría hacer eso en el segundo AUnit
porque Const4
no está dentro del alcance.
Puede tener un efecto en el programa compilado, si no tiene cuidado. Supongamos que tenemos otra unidad que también declara una constante llamada Const4
:
unit BConsts;
interface
const
Const4 = 50;
implementation
end.
Ahora definimos una matriz en UnitA
como esta:
unit AUnit
interface
uses BConsts;
var
data: array[0..Pred(Const4)] of Integer;
implementation
uses AConsts;
procedure Work;
var
i: Integer;
begin
for i := 0 to Const4 - 1 do begin
data[i] := 8;
end;
end;
end.
Ese código escribirá más allá del final de la matriz porque el Const4
que está en el alcance en la sección de interfaz no es el mismo Const4
que se utiliza en la sección de implementación. Esto no sucede a menudo con constantes. Suele suceder con dos identificadores, la función FindClose
definida en Windows
y SysUtils
, y TBitmap
, definida en Graphics
y Windows
. Y en esos dos casos, el compilador le dirá que ha hecho algo mal, aunque no le dirá con precisión que ha usado un identificador que tiene dos significados diferentes. Puede resolver el problema calificando el identificador:
for i := 0 to BConsts.Const4 - 1 do
data[i] := 8;
Si se abordan todas las precauciones anteriores, entonces su programa se compila y se ejecuta correctamente, entonces no importa dónde se usan las unidades. En su ejemplo con App1 y App2, los dos programas serán iguales. No serán idénticos, el compilador habrá procesado las cosas en un orden diferente y, por lo tanto, probablemente coloque las cosas en lugares diferentes, pero no tendrá ningún efecto en la ejecución de su programa.
Los elementos en la declaración de usos en la interfaz son visibles en toda la unidad.
Los elementos en la declaración de usos en la implementación solo son visibles en la sección de implementación.
Ejemplo:
unit A;
interface
const
cA = 1;
..
unit B;
interface
const
cB = 1;
..
unit C;
interface
uses
A;
const
cC1 = cA;
cC2 = cB; // Error
implementation
uses
B;
const
cC3 = cA;
cC4 = cB;
end.
Puede crear unidades dependientes mutuas si se incluye al menos una unidad en la sección de implementación:
unit A;
interface
implementation
uses
B;
end.
unit B;
interface
implementation
uses
A;
end.
Si ambos se usan en la sección de interfaz, no compilarán / vincularán.
Puse todas las referencias en la sección de implementación y solo pongo esos nombres de unidad en la interfaz que tengo que hacer.
Sin embargo, me gusta limitar el alcance de todo tanto como sea posible, y esta política se basa en eso.
Sigo una regla de que pongo todo en la parte Interfaz a menos que tenga que lidiar con problemas con las referencias circulares. Esto ayuda a traer un poco de claridad. Algunos asistentes en Delphi y el cuadro de diálogo "Archivo> Usar unidad ..." colocan unidades en la sección de implementación.
Excepto por las trampas de alcance que Rob Kennedy destacó, no importa. Haga su estándar y quédese con él.