delphi – Doubt regarding reference circular of type customer <-> room

Question:

Well, I had asked but I don't think it was clear so I'll edit as suggested, basically I wanted to make an application in Delphi using a TSala class and several TSala classes, however, the TSala class needs to reference TSala in order to get information from it and to modify it when necessary, and the class room needs a reference to class TPerson in order to create a list of people in the room and to be able to modify those people.

For example: Do something like this somewhere in class TPerson:

self.sala.pegarPessoaPorNome("Alberto").Dar("Refrigerante");

In the TSala class there would be something like this:

function pegarPessoaPorNome(nome: string): TPessoa;
begin
 for pessoa in self.pessoas do
  if pessoa.nome = nome then Exit(pessoa);
end;

However, here comes the problem, since these two classes are in separate units, it would give an error in the "circular reference" compiler because I am using the TSala class in the TPerson class and the TPerssoa class in the TSala class. fix it without having to resort to pointer or TObject?

Answer:

The correct thing, in this case, is for you to create the TSala class as a collection of TPerson (or, the sala class has a field that points to this collection)

You can pulp a lot of code if you already make your classes inheriting from the already defined types TCollection and TCollectionItem.

interface uses System.Classes;

TYPE
TPessoa=Class;{note aqui uma pré-declaração. Permite usar TPessoa em TSala antes de implementa-la}
TSala=Class(TCollection)
public function add:TPessoa;
function pegarPorNome(Nome:String):TPessoa;
property Pessoa(Const Nome:String):TPessoa read pegarPorNome;
constructor create(ItemClass:TCollectionItemClass);
end;

TPessoa=Class(TCollectionItem)
  Nome:String;
  //demais variaveis
  procedure DarQualquerCoisa();
  procedure FazerQualquerCoisa();
end;

implementation

{ TSala }

function TSala.add: TPessoa;
begin
Result := inherited Add as TPessoa;
end;

constructor TSala.create(ItemClass: TCollectionItemClass);
begin
 inherited Create(ItemClass);
end;

function TSala.pegarPorNome(Nome: String): TPessoa;
begin
result := nil;  //se nao encontrar o nome, retorna vazio
for I := 0 to Count-1 do
   begin
     if TPessoa(Items[i]).Nome=Nome then
     begin
     result := Items[i] as TPessoa;
     break;
     end;
   end;
if result = nil then
  showmessage(format('Nome "%s" não encontrado.',Nome));//Nao encontrou esse nome, voce pode emitir um aviso.
end;

{ TPessoa }

procedure TPessoa.DarQualquerCoisa();
begin
;
end;
procedure TPessoa.FazerQualquerCoisa();
begin
;
end;

Finally, how to use this class

procedure TForm1.FormCreate(Sender: TObject);
begin
  Sala1 := TSala.Create;//Sala1 deve ser uma variavel publica
end; 

You can create people in two ways

procedure TForm1.BotaoAddPessoa1Click(Sender: TObject);
var Nova_Pessoa:TPessoa;
begin
 Nova_Pessoa:=Sala.Add;
 Nova_Pessoa.Nome := Edit1.Text;
 //... etc
 Nova_Pessoa.FazerQualquerCoisa();
 Nova_Pessoa.DarQualquerCoisa();
end; 

procedure TForm1.BotaoAddPessoa2Click(Sender: TObject);
begin
//esse é o jeito mais interessante,pois nao precisa declarar variavel
 With Sala.Add do begin
   Nome := Edit1.Text;
//... etc
 FazerQualquerCoisa();
 DarQualquerCoisa();
 end;

end; 
Scroll to Top