technologies reynosa parts mexico empresa autopartes automotive aptiv delphi

reynosa - delphi technologies mexico



Declarar variable global pública en Delphi (3)

el ejemplo muestra Form1 (principal) y Form2 (otro) que tiene un mejor uso para la organización;

Declaración de interfaz FORM1 solamente;

se puede leer de todas las formas;

interface procedure oncreate(Sender: TObject); implementation uses Form2; procedure TForm1.oncreate(Sender: TObject); begin Form2.test1; //{Form2.test2} are not visible to Form1; end;

FORM2 interfaz y declaraciones de implementación;

la declaración de implementación es local a la unidad; no se puede leer de todas las formas;

interface procedure test1; implementation procedure test2; //declared under implementation; procedure TForm2.test1; begin ShowMessage(''form2 test1 message''); end; procedure TForm2.test2; begin ShowMessage(''form2 test2 message''); end; cualquier procedimiento , función , tipo , variable puede ser local para la unidad en implementación;
también hace que intellisense (Ctrl + Space) se limpie de declaraciones usadas solo para la unidad;

Digamos que tengo dos formas en un proyecto delphi, quiero poder acceder a las variables de Form1 desde form2. ¿Hay alguien para declarar, digamos una variable ''pública'' en form1 que se puede leer de todas las formas?

He intentado poner una variable en la declaración pública

{ private declarations } public { public declarations } test: integer; end;

y en la forma 2 tengo

unit Unit2; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, unit1; type { TForm2 } TForm2 = class(TForm) procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); private { private declarations } public { public declarations } end; var Form2: TForm2; implementation {$R *.lfm} { TForm2 } procedure TForm2.FormCreate(Sender: TObject); begin form1 //<---------- DOES NOT GET RECOGNIZED end; end.

Luego coloco ''Unit1'' en la sección de usos en Form2, pero parece que no puedo hacer eso debido a una referencia circular. Me gustaría evitar el uso de punteros si es posible.


En primer lugar, si debe usar globales (probablemente sea mejor no usar globales, como ha señalado sabiamente Craig), debe poner los globales que desea compartir en SharedGlobals.pas:

unit SharedGlobals; interface var {variables here} Something:Integer; implementation { nothing here?}

Ahora usa esa unidad, de las dos unidades en las que quieras compartir el acceso a esa variable. Alternativamente, haz referencia a otro objeto, que se llama algo sensible, y haz que ese objeto sea diseñado como el titular de estado (valores variables) que esas dos instancias (formularios o clases, o lo que sea) deben compartir.

Segunda idea , dado que sus dos unidades ya tienen dependencias entre sí, también podría sortear su dependencia circular utilizando la unidad que crearía una dependencia circular, desde la sección de implementación en lugar de la interfaz:

unit Unit2; interface /// stuff implementation uses Unit1;

...

unit Unit1; interface /// stuff implementation uses Unit2;


Primero , es mejor pretender que los globales no existen en absoluto . Si comienzas a programar con la muleta de variables globales, evitarás aprender las técnicas más simples que te permiten prescindir de ellas. Te preocupa utilizar punteros (lo que en realidad no ayudaría en absoluto a tu problema), pero no te preocupa usar globos globales que en realidad sean más peligrosos.

Globales son peligrosos porque:

  • Proporcionan un enlace entre las unidades que los comparten (un concepto llamado acoplamiento cerrado )
  • Este enlace está oculto en el sentido de que no es obvia la naturaleza exacta del enlace sin examinar los detalles del código.
  • Su código estará lleno de efectos secundarios , lo que quiere decir que cuando hace algo en un método, también suceden otras cosas inesperadas. Esto aumenta la posibilidad y complejidad de errores sutiles.
  • El efecto acumulativo de los puntos anteriores es que incluso si divide un proyecto en 20 unidades, su cerebro todavía tiene que pensar en las 20 unidades al mismo tiempo, como si solo fueran 1 unidad. Esto derrota el propósito de dividir su proyecto en unidades manejables más pequeñas en primer lugar.
  • Descubrirá rápidamente que incluso los proyectos de tamaño mediano comienzan a ser muy difíciles de mantener.

Referencias circulares

Por favor, eche un vistazo a mi respuesta a una pregunta anterior para obtener ideas sobre el tratamiento de referencias circulares en general.

En su caso, simplemente necesita mover la Unit1 de los usos de la interface a los usos de implementation .

var Form2: TForm2; implementation uses Unit1; {$R *.lfm} { TForm2 } procedure TForm2.FormCreate(Sender: TObject); begin Form1.test; //Is now accessible, but remember: it will cause a runtime error if Form1 hasn''t been created or has already been destroyed. end;

Compartir datos sin globales

Notarás que técnicamente sigues usando globales; aunque creados por Delphi y no los tuyos. Aquí hay una técnica que puede usar para compartir datos de una manera más controlada.

unit Unit3; interface type TSharedData = class(TObject) public Test1: Integer; Test2: Integer; end;

Luego en Form1 agregas lo siguiente:

implementation uses ... Unit3; type TForm1 = class(TForm) ... public SharedData: TSharedData; end; //Inside either the constructor or OnCreate event add the following line: SharedData := TSharedData.Create; //Inside either the destructor or OnDestroyevent add the following line: SharedData.Free;

Luego, en Form2 haces algo ligeramente diferente porque quieres usar los datos compartidos de Form1, no sus propios "datos compartidos".

implementation uses ... Unit3; type TForm2 = class(TForm) ... public Form1SharedData: TSharedData; end; //Nothing added to constructor/destructor or OnCreate/OnDestroy events

Finalmente, después de crear ambos formularios, le da a Form2 una referencia a los datos compartidos de Form1 :

procedure RunApplicationWithoutFormGlobals; var LForm1: TForm1; LForm2: TForm2; begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, LForm1); Application.CreateForm(TForm2, LForm2); LForm2.Form1SharedData := LForm1.SharedData; Application.Run; end;

Lo anterior ilustra cuán fácilmente puede deshacerse incluso de las variables globales de Delphi.

Descargo de responsabilidad: Parte del código se aplica a principios de encapsulación generalmente aceptados, pero solo con fines ilustrativos.