2009-02-09 8 views
4

Je ne connais pas le nom de la classe d'objet OWNER. Donc, je dois vérifier partout dans mes codes comme ça:Vérifier le nom de la classe

if TObject(OWNER) is TFirstClass then begin 
    TFirstClass(OWNER).FirstFunction; 
    TFirstClass(OWNER).SecondFunction; 
    ... 
end else 
if TObject(OWNER) is TSecondClass then begin 
    TSecondClass(OWNER).FirstFunction; 
    TSecondClass(OWNER).SecondFunction; 
    ... 
end; 

Y at-il un meilleur moyen? Parce que je dois le faire si la condition dans de nombreux endroits des codes. Toutes les fonctions de TFirstClass et TSecondClass (que je dois exécuter) sont les mêmes.

Note: J'utilise Delphi 5.

+0

Contrôlez-vous OWNER? (Pouvez-vous changer les définitions des classes?) –

+0

De quel type est OWNER. Comme vous êtes en train de taper vers TObject, j'assume Pointer ou Integer/Cardinal? –

Répondre

12

Si vous n'avez pas accès à TFirstClass et TSecondClass, mais souhaitez simplifier votre code, voici une façon:

Créer une classe de base de l'adaptateur:

type 
    TMyAdapter = class(TObject) 
    public 
    procedure FirstMethod; virtual; abstract; 
    procedure SecondMethod; virtual; abstract; 
    end; 

Ensuite, créez les classes descendantes TFirstClassAdapter et TSecondClassAdapter et donnez-leur respectivement une référence privée à l'instance de TFirstClass ou de TSecondClass. Ajoutez un constructeur qui définit cette référence. Remplacer les méthodes des classes d'adaptateur, de sorte qu'ils appellent aux classes adaptées.

type 
    TFirstClassAdapter = class(TMyAdapter) 
    private 
    fObject: TFirstClass; 
    public 
    constructor Create(AAdaptedObject: TFirstClass); 

    procedure FirstMethod; override; 
    procedure SecondMethod; override; 
    end; 

constructor TFirstClassAdapter.Create(AAdaptedObject: TFirstClass); 
begin 
    inherited Create; 
    fObject := AAdaptedObject; 
end; 

procedure TFirstClassAdapter.FirstMethod; 
begin 
    fObject.FirstMethod; 
end; 

procedure TFirstClassAdapter.SecondMethod; 
begin 
    fObject.SecondMethod; 
end; 

Identique pour l'autre classe. Vous n'avez plus qu'à décider si vous allez créer l'adaptateur une seule fois et le transmettre, ou si vous créez une fonction que vous appelez partout où vous en avez besoin, et qui vous donnera un adaptateur pour votre classe concrète. Si vous implémentez l'adaptateur à l'aide d'interfaces, vous n'aurez même pas besoin de gérer la durée de vie de l'adaptateur vous-même.

De cette façon, vous pouvez avoir le comportement polymorphe que Ulrich a donné dans his answer, mais sans avoir besoin de changer TFirstClass et TSecondClass.

+0

+1 pour proposer un motif. Adapterpattern est un modèle pratique à connaître. – Vegar

11

Derive TFirstClass et TSecondClass d'une classe de base commune qui déclare des méthodes virtuelles firstFunction et secondFunction.

Uli.

-1

D'abord excusez-moi pour mon mauvais anglais.
Si vous ne pouvez pas faire les 2 avant les réponses (adaptateurs et dériver d'une classe de base), vous pouvez utiliser RTTI pour accéder à une procédure par son nom.

La procédure doit être déclarée dans la section publiée.

Si vous avez une déclaration comme ceci:

TFirstClass = class(TObject) 
    published 
    procedure FirstFunction; 
    procedure SecondFunction; 
    end; 
    TSecondClass = class(TObject) 
    published 
    procedure FirstFunction; 
    procedure SecondFunction; 
    end 

Vous pouvez faire quelque chose comme ceci pour exécuter une méthode si vous avez le nom:

// Acceso a la rutina; TObject is a Base class for 
    // TFirstClass and TSecondClass 
    Routine.Data := Pointer(obj as TObject); 
    // Devuelve la dirección de un método published; Method for it's name 
    Routine.Code := (obj as TObject).MethodAddress('SecondFunction'); 
    // Not find 
    if (Routine.Code = nil) then Exit; 
    // execute 
    TExecuteMethod(Routine); 

Vous pouvez voir ici des codes similaires:
* Tip4 * Tip7

Cordialement.

Questions connexes