Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Clases recursivas, ¿Como hacerlo? (https://www.clubdelphi.com/foros/showthread.php?t=94187)

josepicd 23-09-2019 16:59:47

Clases recursivas, ¿Como hacerlo?
 
Supongamos que tengo 3 .pas con 1 clase cada uno

La clase 1 contiene un objeto de clase 2 y otro de clase 3.
La clase 2 no contiene nada relevante
La clase 3 contiene un puntero del objeto de la clase 1.

Al meter los uses de da error de redundancia como es de esperar, ¿Como puedo solucionar esto?


----------- file_1.pas --------------------------------------------
uses file_2, file_3;

PC1 = ^TC1;
TC1 = class
f2 : TC2;
f3 : TC3;
end;
----------- file_2.pas --------------------------------------------
TC2 = class
...
end;
----------- file_3.pas --------------------------------------------
uses file_1;

TC3 = class
ptrC1 : PC1
...
end;

dec 23-09-2019 20:10:05

Hola a todos,

Una posible solución puede ser declarar los miembros como "TObject": tú sabes que el objeto será del tipo que sea, y, podrás hacer el "cast" correspondiente, pero, las unidades que declaren dicho tipo podrán ir en la claúsula "implementation", evitando el tipo de error que comentas.

De todas formas, a ver si algún compañero puede dar alguna otra solución. :)

gatosoft 23-09-2019 21:49:10

Cita:

Empezado por dec (Mensaje 533566)
Hola a todos,

Una posible solución puede ser declarar los miembros como "TObject": tú sabes que el objeto será del tipo que sea, y, podrás hacer el "cast" correspondiente, pero, las unidades que declaren dicho tipo podrán ir en la claúsula "implementation", evitando el tipo de error que comentas.

De todas formas, a ver si algún compañero puede dar alguna otra solución. :)

Esa podria ser una solución, pero si existe la opción de definir las clases en la misma unidad, se resolvería el tema de la referencia circular, asi:
Código Delphi [-]
TC3 = class ; //indica que hay una clase llamada TC3 que se definirá mas adelante

TC1= class
  f3: TC3;
end;

TC3= class
  f1: TC1;
end;

Por otro lado, no entiendo la necesidad de PC1 = ^TC1;...

ecfisa 23-09-2019 22:42:44

Hola.

Otra opción es usando interfaces, un ejemplo:

Código Delphi [-]
unit uInter;  

interface

type   
  IClase2 = interface   ['{20FF5573-4A4A-4B1F-975B-817714250A03}'] // ( Ctrl+Shift+G )
    function GetValue: Integer;                  
    procedure SetValue(const  Value:Integer);
 end;

implementation

end.

Código Delphi [-]
unit Unit1; 

interface

uses  uInter; 

type
  TClase1 = class(TObject)
  private
    FValue : Integer;
  public
    Clase2: IClase2;
    constructor Create;
    property Value: Integer read FValue write FValue;
  end;

implementation

constructor TClase1.Create;
begin
  FValue := 111;
end;
end.

Código Delphi [-]
unit Unit2;

interface

uses Unit1, uInter;

type
  TClase2 = class(TInterfacedObject, IClase2)
  private
    FValue : Integer;
  public
    Clase1: TClase1;
    constructor Create;
    function GetValue: Integer;
    procedure SetValue(const  Value:Integer);
  end;

implementation

constructor TClase2.Create;
begin
  FValue := 0;
end;

function TClase2.GetValue: Integer;
begin
  Result := FValue;
end;

procedure TClase2.SetValue(const Value: Integer);
begin
  if Value <> FValue then
    FValue := Value;
end;
end.

Código Delphi [-]
program Project1; {$APPTYPE CONSOLE} {$R *.res}

uses
  System.SysUtils,  Unit1 in 'Unit1.pas',  Unit2 in 'Unit2.pas',  uInter in 'uInter.pas';

var
  Clase1: TClase1;
  Clase2: TClase2;
begin
  // Prueba Clase1
  Clase1 := TClase1.Create;
  Clase1.Clase2 := TClase2.Create;
  Clase1.Value  := 111;
  Clase1.Clase2.SetValue(222);
  Writeln(Clase1.Value, ' ', Clase1.Clase2.GetValue);

  // Prueba Clase2
  Clase2 := TClase2.Create;
  Clase2.Clase1 := TClase1.Create;
  Clase2.Clase1.Value := 333;
  Clase2.SetValue(444);
  Writeln(Clase2.Clase1.Value, ' ', Clase2.GetValue);
 
...

end.
Hay que tener en cuenta que en la interface hay que declarar funciones y procedimientos para acceder o modificar las variables de la clase.


Saludos :)

escafandra 23-09-2019 23:10:59

Creo que lo más sencillo es hacer esto:


Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, 

  unit2, unit3;   //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

type
  TForm1 = class(TForm)
  private
  public
  end;

var
  Form1: TForm1;

implementation


{$R *.dfm}
.........
.........
.........


Código Delphi [-]
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus;

type
  TForm3 = class(TForm)
  private
  public
  end;

var
  Form3: TForm3;

implementation

uses unit1;  //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

{$R *.dfm}
.........
.........
.........




Saludos.

josepicd 24-09-2019 08:24:59

Aqui el problema que tengo es que el uses debe ir en el interface ya que el TForm3 tiene una variable del tipo TForm1 por lo que si lo saco de la implementation y lo pongo en interface tengo el problema de los uses ciclicos


Cita:

Empezado por escafandra (Mensaje 533569)
Creo que lo más sencillo es hacer esto:


Código Delphi [-]
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus;

type
  TForm3 = class(TForm)
  private
F1 : TForm1;
public end; var Form3: TForm3; implementation uses unit1; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< {$R *.dfm} ......... ......... .........




Saludos.


mamcx 24-09-2019 16:18:59

Ten en cuenta que clases recursivas muchas veces es un anti-patron.

Igual a que esas clases sean forms (deberias comunicar datos, no formularios).

En Delphi, una manera elegante de resolverlo es con interfaces. Puedes implementar interfaces para comunicar datos y transpasar "fronteras" manteniendo los principios de

SOLID.

P.D: Algo que he aprendido luego de usar mas de 12 lenguajes es que cuando algo se hace "dificil" es, muchas veces, el mismo lenguaje indicando que hay otro camino mejor y mas idiomatico.

josepicd 24-09-2019 16:22:27

Muchas gracias a todos, al final he encontrado la forma de sacarlo de interface y meterlo en implementacion, asi todo resuelto.


Gracias por el esfuerzo


La franja horaria es GMT +2. Ahora son las 12:11:07.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi