Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: AndreaM - Luglio 23, 2013, 12:52:30 pm

Titolo: Liste di Classi
Inserito da: AndreaM - Luglio 23, 2013, 12:52:30 pm
Salve a tutti!
Ho creato una mia classe, e nel mio programma ho la necessita di utilizzare numerose istanze di questa classe, tenute in una lista usando TFPObjectList.
Il tutto funziona bene, ma quando devo usare la mia classe devo fare:

Codice: [Seleziona]
TMyClasse(Lista[i]).miaProprieta

Lo faccio e il tutto funziona bene!
Pero mi chiedevo, è possibile creare una classe che mi permetta di usare la mia in questo modo?

Codice: [Seleziona]
MiaClasse[i].miaProprieta

in pratica dovrei usare una lista che contiene la mia classe!

Come posso fare?
Grazie a tutti!
P.S. Sto lavorando ad un progetto per la gestione dei file GPS

Titolo: Re:Liste di Classi
Inserito da: nomorelogic - Luglio 23, 2013, 01:13:48 pm
ci sono molte strade per fare quello che dici

una abbastanza semplice (di sicuro non la più efficiente) è quella di fare una classe wrapper per usare TFPObjectList con tuoi metodi e proprietà

es:
Codice: [Seleziona]
TMyClasseManager = class(TObject)
private
   lista: TFPObjectList;
public
   constructor Create...
   destructor Destroy...
   function New: TMyClasse;
   procedure Add(instance: TMyClasse);

   property Items... default
end;


Titolo: Re:Liste di Classi
Inserito da: AndreaM - Luglio 23, 2013, 06:30:51 pm
Gerazie Nomo,
Mi hai dato lo spunto per guardare come è stato fatto TFPObjectList;
Ed ho visto che anche questa è una classe wrapper di TFPlist;
Ho creato questo codice che sembra funzionare, ma è possibile renderlo più efficiente?

Codice: [Seleziona]
unit Unit3;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils,contnrs;
type
  { Tcane }
  TCane = class(TObject) // Classe base di prova
  private
    FNome:string;
  public
    Constructor Create;
    destructor Destroy; override;
    Property Nome:string read Fnome write Fnome;
  end;

  { TCani }
  TCani = class(TObject) // Classe Lista dei Cani
   Private
     Flist:TFPObjectList; // lista interna
     function GetCount: integer;
     function GetItem(Idx: integer): Tcane; // Restituisce istanza di Tcane
     procedure SetItem(Idx: integer; AValue: Tcane); // Crea istanza di Tcane
   Public
     constructor Create;
     Destructor Destroy; override;
     Function New(Aname:string):Integer; // aggiunge un cane alla lista
     Procedure Delete(Idx:Integer); // Cancella un cane dalla lista
     Property Items [Idx:integer]: Tcane read GetItem write SetItem; default;
     Property Count:integer read GetCount;
  end;

implementation

{ TCani }

function TCani.GetItem(Idx: integer): Tcane;
begin // restituisce istanza di Tcane alla posizione Idx
  Result:=Tcane(FList[Idx]);
end;

function TCani.GetCount: integer;
begin  // Totale dei cani presenti
  Result:=Flist.Count;
end;

procedure TCani.SetItem(Idx: integer; AValue: Tcane);
begin // Imposta proprieta del cane Idx
  Flist[Idx]:=AValue;
end;

constructor TCani.Create;
begin // creo il componente
  inherited Create;
  FList := TFPObjectList.Create;
end;

destructor TCani.Destroy;
begin // Distruggo il componente
  if (FList <> nil) then
  begin
    Flist.Clear;
    FList.Destroy;
  end;
  inherited Destroy;
end;

function TCani.New(Aname: string): Integer;
var cane:Tcane;
begin // Creo una nuova istanza del cane e lo aggiungo alla lista
cane:=TCane.Create;
cane.Nome:=Aname;
Result:=Flist.Add(cane);
end;

procedure TCani.Delete(Idx: Integer);
begin // cancello il cane
  flist.Delete(idx);  // cancello istanza sulla lista
end;

{ Tcane }

constructor TCane.Create;
begin
  inherited Create;
end;

destructor Tcane.Destroy;
begin
  inherited Destroy;
end;

end.           

Ovviamente ho iserito solo le cose di base per provare se tutto funziona!
Grazie

Titolo: Re:Liste di Classi
Inserito da: xinyiman - Luglio 23, 2013, 07:48:13 pm
prova a seguire una di queste due guide

http://www.lazaruspascal.it/index.php?page=18

http://www.lazaruspascal.it/index.php?page=57

dovrebbero fare al caso tuo e ogni nodo della lista lo istanzi con la tua classe
Titolo: Re:Liste di Classi
Inserito da: nomorelogic - Luglio 24, 2013, 09:23:34 am
Ho creato questo codice che sembra funzionare, ma è possibile renderlo più efficiente?

l'efficienza dipende da come devi usare la lista, dipende dal numero di elementi che deve contenere, se il numero è sempre quello o no, quanti cast ci sono e quanto spesso, se servono degli ordinamenti o no, dal metodo di ricerca, ecc...

in generale se non hai necessità specifiche (es: numero enorme di elementi da gestire), sei già a buon punto ;)
se invece devi limare i tempi, le guide segnalate da xini ti possono dare uno spunto sicuramente.
Titolo: Re:Liste di Classi
Inserito da: Stilgar - Luglio 24, 2013, 11:39:39 am
Se vuoi, al posto di "wrappare" la lista, puoi sempre estenderla.
Quindi hai una lista "specializzata".
I cast vengono fatti all'interno. Da "fuori" puoi sempre accedere anche ai vecchi metodi.

Per efficente cosa intendi?
Titolo: Re:Liste di Classi
Inserito da: AndreaM - Luglio 25, 2013, 09:28:26 am
Grazie a tutti!
Ora ho capito cosa si intende per efficienza! Il numero degli elementi può variare ma cmq rimane nell'ordine delle centinaia, ho fatto delle prove con grosse q.tà e sono osoddisfatto!
Per Stilgar: Io in effetti ho una lista di oggetti creati da me! Cosa intendi per lista specializzata? Puoi farmi un esempio?
 
Titolo: Re:Liste di Classi
Inserito da: Stilgar - Luglio 25, 2013, 03:18:39 pm
Codice: [Seleziona]

TListaSpecializzata = class(TList)
public
  property Items[index : integer] : <lamiaclasse> read getItem write setItem;  default;
end;

In questo modo l'accesso ai dati è "nascosto" dentro il metodo get e set. Qui esegui il cast nel get e non devi più farlo da fuori.

con la keyword "default" indichi al compilatore di fare riferimento a quella proprietà quando trova una costruzione sintattica del tipo:

Codice: [Seleziona]
 istanzaDellaMiaLista[indice] := istanza;
 istanza := istanzaDellaMiaClasse[indice];

Spero di essere stato chiaro e di non aver creato più confusione di prima ... ;)

Stilgar