Bonjour,
Merci à toi aussi pour cette lecture attentive
Envoyé par
BeanzMaster
strict private: l'élément n'est visible que par un élément de la même classe ; --> sauf par transtypage non ?
private: l'élément n'est visible que par un élément présent dans la même unité;
--> idem que ci-dessus
--> et qu'entend tu par élément ???? une procédure de la classe ? ( une fonction hors de la classe, mais dans la même unité n'aura pas accès a ces données, non ? )
--> "un élément présent dans la même unité" ça ne serait pas plutôt par un élément de la même classe comme "strict"
Non, pas de transtypage qui tienne ! En revanche, une fonction hors de la classe, mais dans la même unité, aura accès à ces données y compris privées (si elle accède à une instance d'une classe, bien sûr). Donc, je maintiens les définitions.
Je vais en revanche apporter un exemple pour preuve et te remercie pour cette remarque
.
Voici tout d'abord l'unité d'un projet qui définit mes classes, ainsi qu'une procédure indépendante :
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| unit other;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
type
{ TMyClass }
TMyClass = class
strict private
fMyStrictPrivateField: Integer;
private
fMyPrivateField: Integer;
public
fMyPublicField: Integer;
function InternalMyFunct: Integer;
end;
{ TMyOtherClass }
TMyOtherClass = class
public
ASubClass: TMyClass;
constructor Create;
destructor Destroy; override;
end;
{ MyThirdClass }
MyThirdClass = class(TMyClass)
public
function MyFunc: Integer;
end;
procedure MyProc;
implementation
procedure MyProc;
var
AnObject: TMyClass;
begin
AnObject := TMyClass.Create;
try
AnObject.fMyPublicField := 1;
AnObject.fMyPrivateField := 3;
//AnObject.fMyStrictPrivateField := 2; ne compile pas
finally
AnObject.Free;
end;
end;
{ MyThirdClass }
function MyThirdClass.MyFunc: Integer;
begin
Result := fMyPrivateField;
//Result := fMyStrictPrivateField; ne compile pas
end;
{ TMyClass }
function TMyClass.InternalMyFunct: Integer;
begin
Result := fMyStrictPrivateField;
end;
{ TMyOtherClass }
constructor TMyOtherClass.Create;
begin
inherited;
ASubClass := TMyClass.Create;
ASubClass.fMyPrivateField := 1;
ASubClass.fMyPrivateField := 4;
// ASubClass.fMyStrictPrivateField:= 5; ne compile pas
end;
destructor TMyOtherClass.Destroy;
begin
ASubClass.Free;
inherited Destroy;
end;
end. |
On voit que les champs privés ne le sont pas vraiment puisqu'ils sont même accessibles par une procédure indépendante qui instancie une classe définie dans l'unité. D'où l'intérêt de
strict private qui interdit tout accès, y compris à une classe qui descend de la première.
A présent, si l'on crée un autre unité faisant référence à celle qui définit les classes, les choses changent, car ce qui est privé n'est plus accessible :
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
|
unit other2;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, other;
type
{ TMyFourthClass }
TMyFourthClass = class(TMyClass)
public
procedure MyProc;
end;
procedure MyProc;
implementation
procedure MyProc;
var
AnObject: TMyClass;
begin
AnObject := TMyClass.Create;
try
AnObject.fMyPublicField := 1;
// AnObject.fMyPrivateField := 3; ne compile pas
//AnObject.fMyStrictPrivateField := 2; ne compile pas
finally
AnObject.Free;
end;
end;
{ TMyFourthClass }
procedure TMyFourthClass.MyProc;
begin
fMyPublicField:= 7;
//fMyPrivateField := 9; ne compile pas
//fMyStrictPrivateField := 10; ne compile pas
end;
end. |
J'ai choisi une procédure indépendante et une classe fille. Dans les deux cas, ce qui était accessible dans la même unité ne l'est plus hors de l'unité : le privé est enfin privé !
Envoyé par
BeanzMaster
strict protected: l'élément n'est utilisable que par un descendant de la classe (donc une classe dérivée) présent dans l'unité ou dans une autre unité que celle de la classe ;
protected: l'élément n'est utilisable que par un descendant de la classe, qu'il soit dans l'unité de la classe ou dans une autre unité y faisant référence, ou par une autre classe présente dans l'unité de la classe ;
--> les 2 c'est pareil, non ?
Pas tout à fait : comme indiqué, avec
protected, une autre classe (donc quelconque) qui figure dans l'unité de définition de la classe où apparaît ce protected a accès aux méthodes et aux champs protégés. Avec
strict protected, il faut être descendant de la classe pour y avoir accès : une classe non dérivée, même si elle figure dans la même unité que la classe qui comprend le strict protected, n'aura pas accès à ces éléments (champs ou méthodes). Là aussi, un exemple détaillé s'impose sans doute...
Remarque complémentaire : les détails donnés ici ne concernent pas vraiment les débutants en POO qui utiliseront assez facilement les "classiques"
private,
protected,
public et
published et s'abstiendront sans doute d'utiliser les dérivés
strict. Ces derniers ne sont pas pour faire "joli" et intéressent tout spécialement les projets assez ambitieux. Je pense par ailleurs que
strict private devrait devenir un réflexe tant cette section est utile afin d'éviter les manipulations risquées de champs.
J'ai conscience de ne pas pouvoir répondre, même en 26 pages, à toutes les questions, mais je promets de proposer des exercices/exemples complémentaires qui illustreront ces problèmes, sans doute dans un tutoriel du genre "Exercices sur la POO". Encore merci pour l'intérêt porté à ce tutoriel perfectible, c'est certain
.
Cordialement,
Gilles
1 |
0 |