Modification de la taille d'un tableau dynamique pré-déclaré dans une classe
olemtiri
Messages postés8Date d'inscriptionvendredi 19 novembre 2004StatutMembreDernière intervention 3 décembre 2006
-
26 nov. 2006 à 16:54
olemtiri
Messages postés8Date d'inscriptionvendredi 19 novembre 2004StatutMembreDernière intervention 3 décembre 2006
-
3 déc. 2006 à 22:16
Slt à vous, j'ai un petit problème en ce qui concerne la modification de la taille d'un tableau(pas n'importe quel tableau dynamique mais un tableau déclaré comme propriété d'une classe). Voici un exemple de code :
type
ByteArray=array of Byte;
TEssai=class(TObject)
private
Fvar1:ByteArray;
public
property var1:ByteArray read Fvar1 write Fvar1;
end;
Je crée ensuite un bouton standard et j'ajoute le code suivant :
procedure TForm1.Button1Click(Sender: TObject);
var Essai:TEssai;
begin
SetLength(Essai.var1,2);
end;
mais là ca ne marche pas et je reçois l'erreur : "Un objet constante ne peut être passé comme paramètre Var".
Je sais qu'il y a une solution c'est de créer une méthode associée à cette classe pour modifier la taille de ce tableau, mais le problème c'est qu'en pratique j'ai plusieurs tableaux dynamiques (même beaucoup) donc ça ne serait pas efficace de créer 10 ou 11 fonctions pour changer la taille des tableaux.
Quelqu'un aurait-il une solution pour ce problème?
DRJEROME
Messages postés436Date d'inscriptionjeudi 9 janvier 2003StatutMembreDernière intervention 5 février 2015 26 nov. 2006 à 18:47
tu peux écrire "Fvar1" à la place de "var1" et "Fvar2" à la place de "var2" dans la procédure "Button1Click"
(pour la justesse du code) sinon le raisonnement reste valable
olemtiri
Messages postés8Date d'inscriptionvendredi 19 novembre 2004StatutMembreDernière intervention 3 décembre 2006 26 nov. 2006 à 20:08
J'ai déjà essayé ce truc, merci tt de même. J'ai remarqué d'ailleurs qu'il était possible de manipuler les tableaux dynamiques en leur affectant d'autres tableaux dynamiques. Comme solution c'est bien pour de petites applications mais je parle là d'un projet un peu volumineux et mettre en place cette solution veut dire doubler le nombre de variables à utilser. N'y aurait-il pas une autre alternative?
type TByteArray = array of Byte;
TEssai = class(TObject)
private Fvar1:TByteArray;
FDataByte : Byte;
Procedure SetByteArray(Const Index: Integer; Value: Byte);
Function GetByteArray(Const Index: Integer): Byte;
public Destructor Destroy; OverLoad;
property DataByte[Const Index: Integer]: Byte read GetByteArray write SetByteArray;
end;
implementation
{ TEssai }
destructor TEssai.Destroy;
begin Finalize(FVar1);
Inherited Destroy;
end;
function TEssai.GetByteArray(const Index: Integer): Byte;
begin If Index < = High(FVar1) Then
Result : = FVar1[Index];
end;
procedure TEssai.SetByteArray(const Index: Integer; Value: Byte);
begin If Index > High(FVar1) + 1 Then Exit;
If Index > High(FVar1) Then SetLength(FVar1, Length(FVar1) + 1);
FVar1[Index] := Value;
end ;
end.
Utilisation :
Uses UEssai;
procedure TForm1.Button1Click(Sender: TObject);
Var aTest : TEssai;
I : Integer;
begin Randomize;
aTest : = TEssai.Create;
Try For I := 0 To 10 do aTest.DataByte[I]: = Random(256);
For I := 0 to 10 do Memo1.Lines.Add(IntToStr(aTest.DataByte[I]));
Finally aTest.Free;
End;
end;
type TByteArray = array of Byte;
TEssai = class(TObject)
private Fvar1:TByteArray;
Procedure SetByteArray(Const Index: Integer; Value: Byte);
Function GetByteArray(Const Index: Integer): Byte;
public Procedure Clear;
Destructor Destroy; override;
property DataByte [Const Index: Integer]: Byte read GetByteArray write SetByteArray;
end;
implementation
{ TEssai }
{Mise à Zéro } procedure TEssai.Clear;
begin SetLength(FVar1, 0);
end;
destructor TEssai.Destroy;
begin Clear;
Finalize(FVar1);
Inherited Destroy;
end;
function TEssai.GetByteArray(const Index: Integer): Byte;
begin Result : = 0;
If Index < = High(FVar1) Then Result := FVar1[Index];
end ;
procedure TEssai.SetByteArray(const Index: Integer; Value: Byte);
begin If Index > High(FVar1) + 1 Then Exit;
If Index > High(FVar1) Then SetLength(FVar1, Length(FVar1) + 1);
FVar1[Index] : = Value;
end;
end.
La démo reste la même, le clear est la si tu réutilise l'objet TEssai tu peut remettre le tableau à zéro juste en faisant un Clear :
Ex. aTest.Clear;
voilà c'est la base si tu as besoin de plus il est facile de rejouter des procédure et/où fonction
olemtiri
Messages postés8Date d'inscriptionvendredi 19 novembre 2004StatutMembreDernière intervention 3 décembre 2006 2 déc. 2006 à 19:05
Merci, la solution a marché. Or un autre problème se pose, maintenant supposons que le tableau que je veux modifier est celui ci :
FVar1:array of record
Name:string;
Age:Byte;
Var2:array of Byte;
end;
alors comment faire pour modifier les différentes variables de FVar1. La complexité vient du fait qu'il y a un tableau à l'intérieur d'un autre tableau. Pour une généralisation,est-ce qu'il n y a pas une solution pour toutes les combinaisons possibles de array et record? Merci, j'apprécie votre aide.
P.S : Je ne cherche pas poser ces problèmes comme ça sans raison, mais c'est vraiment le projet sur lequel je travaille qui m'a imposé ces difficultés.
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 2 déc. 2006 à 21:17
Si tu as un array of record dans une classe, ça devient vite difficile d'y avoir accès simplement.
En effet, tu vas être contronté à des erreurs du type "partie gauche non affectable" et tout ça, à cause des propriétés.
La solution qui marche bien est de passer par un TObjectList et une classe au lieu du record.
Exemple:
<hr size= "2" width="100%" />TVar1 = class (TObject)
public Name: string;
Age: Byte;
end;
constructor TEssai.Create;
begin
inherited Create;
FVar1 := TObjectList.Create(True);
end ;
destructor TEssai.Destroy;
begin FVar1.Free;
inherited Destroy;
end;
function TEssai.GetVar1(I: Integer): TVar1;
begin Result : = FVar1[I] as TVar1;
end;
function TEssai.GetVar1Count: Integer;
begin Result := FVar1.Count;
end ;
<hr size ="2" width="100%" />
Bon, je n'ai pas inclus de fonction d'ajout ni autre chose ...
Mais l'idée est là, l'essentiel aussi.
Renseigne toi sur la classe TObjectList, elle est la clé de voûte de pas mal de problèmes du genre et ce serait dommage de passer à côté.
@ Cirec: l'utilité des paramètres "const" n'est justifiée que si le paramètre ne doit pas être modifié et que son occupation mémoire dépasse 32 bits. Elle indique à Delphi qu'il peut envoyer directement un pointeur sur la copie originale de la variable sans soucis. Pour un Integer, il n'y a aucun gain, voie même une perte puisque Delphi va passer l'adresse de l'Integer au lieu de sa valeur directement dans le registre EBX.
En gros: ''const'' est à utiliser (entendre bénéfique) pour les types chaînes, tableaux et record.
olemtiri
Messages postés8Date d'inscriptionvendredi 19 novembre 2004StatutMembreDernière intervention 3 décembre 2006 3 déc. 2006 à 22:16
Merci cirec et Florent pour votre aide. J'ai trouvé une solution plus ou moins appropriée mais qui s'est adaptée facilement. J'ai juste remplacé quelques propriétés qui posaient problème avec des variables. Comme ca pas d'erreur, mais c'est bien de savoir le TObjectList et l'autre soluce par cirec.
Merci encore.