par , 23/08/2016 à 20h30 (624 Affichages)
Il est intéressant de noter que les classes acceptent des éléments plutôt inattendus et par conséquent peu utilisés : des sections const et type sont possibles et fonctionnent comme elles le feraient dans une unité, une méthode, une procédure ou une fonction.
Ainsi les déclarations suivantes sont-elles correctes :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
type
{ TMyClass }
TMyClass = class
const
MyConst = 'developpez.com';
type
TMyEnum = (one, two, three);
{ TMyNestedClass }
TMyNestedClass = class
strict private
fMyNestedField: string;
fMyNestedEnum: TMyEnum;
function GetMyNestedEnum: TMyEnum;
function GetMyNestedField: string;
procedure SetMyNestedEnum(const AValue: TMyEnum);
procedure SetMyNestedField(const St: string);
public
property MyNestedField: string read GetMyNestedField write SetMyNestedField;
property MyNestedEnum: TMyEnum read GetMyNestedEnum write SetMyNestedEnum;
end;
private
fMyNestedClass: TMyNestedClass;
function GetMyProperty: string;
public
constructor Create;
destructor Destroy; override;
property MyProperty: string read GetMyProperty;
end; |
La classe TMyClass comprend une section pour les constantes et une pour les types. Parmi ces derniers, en plus d'une énumération, vous pouvez voir une classe qui vient se nicher dans la première !
La seule véritable difficulté pourrait être l'accès à cette classe interne. En fait, rien de plus simple : le niveau d'imbrication des membres de l'expression est déterminé par des points supplémentaires. Par exemple :
procedure TMyClass.TMyNestedClass.SetMyNestedField(const St: string);
Le code source de cette classe englobant une autre pourrait alors être celui-ci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
{ TMyClass }
function TMyClass.GetMyProperty: string;
// *** propriété pour retrouver la propriété de l'objet interne ***
begin
Result := fMyNestedClass.MyNestedField;
end;
constructor TMyClass.Create;
begin
inherited Create;
fMyNestedClass := TMyNestedClass.Create;
// la propriété contient la valeur de la constante interne
fMyNestedClass.MyNestedField := MyConst;
// la propriété contient une valeur de l'énumération
fMyNestedClass.MyNestedEnum := one;
end;
destructor TMyClass.Destroy;
// *** destruction de l'objet avec l'objet interne ***
begin
fMyNestedClass.Free;
inherited Destroy;
end;
{ TMyClass.TMyNestedClass }
function TMyClass.TMyNestedClass.GetMyNestedField: string;
// *** valeur de la propriété chaîne interne ***
begin
Result := fMyNestedField;
end;
function TMyClass.TMyNestedClass.GetMyNestedEnum: TMyEnum;
// *** valeur de la propriété énumération interne ***
begin
Result := fMyNestedEnum;
end;
procedure TMyClass.TMyNestedClass.SetMyNestedEnum(const AValue: TMyEnum);
// *** fixe la valeur de la propriété énumération interne ***
begin
fMyNestedEnum := AValue;
end;
procedure TMyClass.TMyNestedClass.SetMyNestedField(const St: string);
// *** fixe la valeur de la propriété chaîne interne ***
begin
fMyNestedField := St;
end; |
La différence essentielle entre ces constantes et types compris dans une classe et ceux habituellement utilisés dans une unité ou une routine tient au fait qu'ils sont sensibles à la portée avec laquelle ils ont été définis : par exemple, un type défini dans une classe avec une portée strict private ne sera pas visible par une autre classe de la même unité.
Pour ce qui est des variables au sein d'une classe, souvenez-vous que les champs sont des variables, mais que le mot réservé var est facultatif. Ici encore, une différence avec les variables globales ou locales ordinaires : une variable définie au sein d'une classe peut être précédée du mot class, ce qui la rend équivalente à une variable déclarée au niveau de l'unité, mais dont l'accès doit alors être pleinement qualifié :
1 2 3 4 5 6 7
| TMyClass = class
class var MyVar: string;
end;
[...]
TmyClass.MyVar:= 'Bonjour !'; |