2010-08-22 5 views
0

je une classe définie comme:Delphi - Créer une instance de la sous-classe

TfraFrame = class(TFrame); 

alors j'ai plusieurs sous-classes tous inherting de cela, tels que:

TfraUsers = class(TfraFrame); 
TfraGroups = class(TfraFrame); 
TfraMenus = class(TfraFrame); 

Dans ma principale forme que je l'ai déclaré variables comme:

var 
    fraUsers: TfraUsers; 
    fraGroups: TfraGroups; 
    fraMenus: TfraMenus; 

Maintenant ma question est, je voudrais avoir une seule fonction pour contrôler la génératio n des instances de chaque classe. Il ne devrait y avoir qu'une instance de chaque classe, mais je veux seulement créer les instances si l'utilisateur les requiert.

Je voudrais passer la variable comme ceci:

procedure ShowFrame(Frame: TfraFrame) 
begin 
    if Frame = nil then 
    begin 
    Frame := TfraFrame.Create(self); 
    Frame.Init(Panel1); 
    end; 

    Frame.Show; 
end; 

et l'appeler comme celui-ci;

ShowFrame(fraUsers); 

Je l'attendais pour créer une instance de TfraUsers (parce que c'est ce que fraUsers est déclaré), cependant, je pense qu'il peut créer une instance de fraFrame.

Y at-il un moyen de créer une instance du type que la variable a été déclarée comme?

Répondre

3

Eh oui, vous avez besoin de dire showFrame quelle classe instancier:

ajouter

type 
    tfraFrameClass = class of TfraFrame; 

juste après la déclaration de tfraFrame. Et changer showFrame à:

function ShowFrame(Frame: TfraFrame; FrameClass: TfraFrameClass): TfraFrame; 
begin 
    if Frame = nil then 
    begin 
    Result := FrameClass.Create(self); 
    Result.Init(Panel1); 
    end 
    else 
    Result := Frame; 

    Result.Show; 
end; 

Notez que vous ne pouvez pas passer cadre comme paramètre var comme le compilateur insistera sur déclarés et le type réel du paramètre passé à être exactement la même chose.

Mise à jour Exemple mis à jour pour afficher l'image lorsqu'elle était déjà affectée.

Mise à jour j'oublié de mentionner que l'attribution du résultat de l'appel Créer dans le code de l'OP pour la procédure de showFrame ne fonctionnerait pas. Si elle n'était pas déclarée comme var, l'assignation ne dépasserait pas la portée de la procédure showFrame, la valeur de la variable passée dans showFrame ne serait pas modifiée. Le déclarer comme var ne fonctionnerait pas non plus comme mentionné ci-dessus. La solution est de faire ce que suggère @Andreas: utiliser un pointeur non typé; ou en faire une fonction comme je l'ai fait. Bien sûr (sourire), je préfère le mien car cela préserve la sécurité de type un peu mieux.

aussi, bien sûr, dans mon exemple l'intention était d'avoir le résultat de la fonction showFrame affectée à la variable de cadre approprié, comme ceci:

fraUsers := showFrame(fraUsers, TfraUsers); 

Mise à jour Ou, comme Sertac a souligné, vous pouvez toujours utiliser la procédure avec un paramètre var lorsque vous effectuez un cast sur la variable que vous passez à showForm.

procedure showFrame(var Frame: TfraFrame; FrameClasse: TfraFrameClass); 
begin 
    if Frame = nil then 
    begin 
    Frame := FrameClass.Create(self); 
    Frame.Init(Panel1); 
    end; 

    Frame.Show; 
end; 

et l'appeler comme:

showFrame(TfraFrame(fraUsers), TFraUsers); 
+1

Je pense que l'OP veut le cadre de montrer si elle est affectée ... –

+0

Oui, alors qu'est-ce qui l'empêche d'affecter le résultat de la fonction à la var? Il pensait probablement dans son code original que cela fonctionnerait en assignant le résultat du paramètre Créer au paramètre transmis, mais cela ne fonctionnerait pas, même s'il était déclaré comme var car avec les paramètres var, Delphi se plaindrait de la réalité. et les types déclarés étant différents. –

+0

@Andreas, oh diable, oubliez mon commentaire. Lisez le vôtre mal. –

0

Je suggère que vous faites vos propriétés variables cadre

property fraUsers: TfraUsers read GetfraUsers write ffraUsers; 
.. 

function GetFraUsers: TFraUsers; 
begin 
    if fFraUsers = nil then 
    fFraUsers := TfraUsers.Create(...); 
    Result := ffraUsers; 
end; 

Then 

procedure ShowFrame(Frame: TfraFrame) 
begin 
    Frame.Init(Panel1); 
    Frame.Show; 
end; 

procedure form1.Button1Click(...) 
begin 
    ShowFrame(fraUsers); // creates the frame if it does not exist 
end; 
Questions connexes