IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Changer la visibilité du constructeur


Sujet :

Langage Delphi

  1. #1
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut Changer la visibilité du constructeur
    Bonjour
    Je cherche à implémenter le pattern "Singleton" dans mon appli.
    J'ai besoin de changer la visibilité de mon constructeur de classe pour le mettre en "private" ou "protected" et déleguer la construction de mon singleton à une methode de classe du genre "getInstance()".
    En clair je souhaite faire ceci.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    TMaclasse=class
     private
      ///Redéfinition du constructeur de classe
      constructor create();reintroduce;
     public
      ///Crée une seule instance de TMaclasse ou renvoie celle déja créée
      class function getInstance():TMaClasse;
      .....
    end;
    Mon problème est-que le constructeur create() reste visible en dehors de l'unité contenant TMaclasse.
    Quelqu'un a une idée de comment je peux faire ça?...ou est-ce possible de changer la visibilité de mon constructeur;
    Je précise que je suis sous Delphi 2005.

    Merci
    Pensons bien, pensons bio

  2. #2
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    Dans le même ordre d'idée : est-il possible de changer la visibilité du destructeur pour le rendre inaccessible hors de mon unité?
    Merci.
    Pensons bien, pensons bio

  3. #3
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut

    Citation Envoyé par samaury Voir le message
    J'ai besoin de changer la visibilité de mon constructeur de classe pour le mettre en "private" ou "protected"
    Pourquoi ce besoin impérieux ?

    La définition d'une classe Singleton n'est pas très compliquée en elle-même. Contrôler l'unicité de l'instance de la classe ne nécessite pas a priori de changer la visibilité du constructeur/destructeur.

    @+ Claudius.

  4. #4
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    Pourquoi ce besoin impérieux ?
    Je ne serai pas le seul à utiliser cette classe. Il s'agit d'une classe utilitaire que d'autres collègue auront à utiliser. Mon but est de les obliger à utiliser le getInstance() plutot que un create() pour instancier la classe.

    La définition d'une classe Singleton n'est pas très compliquée en elle-même. Contrôler l'unicité de l'instance de la classe ne nécessite pas a priori de changer la visibilité du constructeur/destructeur.
    Je suis bien d'accord. Mais pour la raison exposée plus haut masquer le create() me paraissait plus "propre" mais si ce n'est pas possible, je me contenterais de mon getInstance() sans masquer le create()
    Merci
    Pensons bien, pensons bio

  5. #5
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Citation Envoyé par samaury Voir le message
    Mon but est de les obliger à utiliser le getInstance() plutot que un create() pour instancier la classe.
    Mouais. Je suis peut-être trop conventionnel.

    Perso je définirais ma classe ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    interface
     
    type
      TSingleton = class
      strict private
        class var
          FInstance: TObject;
          FRefCount: Integer;
      private
          FList: TList;
          F1: Integer;
      public
        destructor Destroy; override;
        class function NewInstance: TObject; override;
        procedure FreeInstance; override;
        class function RefCount: Integer;
      end;
     
    implementation
     
    { TSingleton }
     
    destructor TSingleton.Destroy;
    begin
      FList.Free;
      inherited;
    end;
     
    procedure TSingleton.FreeInstance;
    begin
      Assert(FRefCount > 0);
     
      Dec(FRefCount);
      if FRefCount = 0 then
      begin
        FInstance := nil;
        inherited;
      end;
    end;
     
    class function TSingleton.NewInstance: TObject;
    begin
      if not Assigned(FInstance) then
      begin
        FInstance:= inherited NewInstance;
        FRefCount := 0;
        // Init des variables privées
        with TSingleton(FInstance) do
        begin
          FList := TList.Create;
          F1 := 0;
        end;
      end;
      Result := FInstance;
      Inc(FRefCount);
    end;
     
    class function TSingleton.RefCount: Integer;
    begin
      Result := FRefCount;
    end;
     
     
    // Utilisation
     
    var
      o1, o2, o3: TSingleton;
    begin
      o1 := TSingleton.Create;
      o2 := TSingleton.Create;
      o3 := TSingleton.Create;
      ShowMessage(Format('RefCount: %d', [TSingleton.RefCount]));
     
      o1.Free;
      o2.Free;
      o3.Free;
      ShowMessage(Format('RefCount: %d', [TSingleton.RefCount]));
    end;
    Une instance unique de la classe avec un comptage de référence.
    Cela me parait plus "conventionnel" voire plus simple.

    @+ Claudius

  6. #6
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Plutôt que masquer le create, autant raisé une exception dedans.

    Voici mon idée:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
      TTest = class sealed
      private
        class var
          FCanCreate: Boolean;
          FInstance: TTest;
      public
        constructor Create;
        class function GetInstance: TTest;
      end;
     
    implementation
     
    constructor TTest.Create;
    begin
      if not TTest.FCanCreate then
        raise Exception.Create('Utilisez la méthode GetInstance sinon je vous tire les oreilles :)');
    end;
     
    class function TTest.GetInstance: TTest;
    begin
      if FInstance = nil then
      begin
        TTest.FCanCreate := True;
        FInstance := TTest.Create;
        TTest.FCanCreate := False;
      end;
      Result := FInstance;
    end;
     
    initialization
     
    finalization
      if TTest.FInstance <> nil then
        TTest.FInstance.Free;
    Akim Merabet

  7. #7
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Mouais. Je suis peut-être trop conventionnel.
    J'ai pas tout compris mais on va dire que on est lundi et que mon neurone n'est pas encore sorti d'hibernation...

    Perso je définirais ma classe ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ...
      strict private
        class var
          FInstance: TObject;
          FRefCount: Integer;
    ...
    J'ai peur que les appli win32 ne supportent pas le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    strict private
        class var
    comme déclaration à l'intérieur d'une classe, à moins que ce soit D2005...ou alors je m'y prends vraiment très mal.
    Du coup mon équivalent de ton "FInstance" est déclaré dans la partie implementation de mon unité pour n'être accessible que localement.
    Merci
    Pensons bien, pensons bio

  8. #8
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    if not TTest.FCanCreate then
    raise Exception.Create('Utilisez la méthode GetInstance sinon je vous tire les oreilles ');
    C'est à peu de chose près ce que j'ai fais mais en plus...menaçant
    Pensons bien, pensons bio

  9. #9
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    plus menacant c'est quoi tirage de coucouniettes?
    Akim Merabet

  10. #10
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    utilise un TInterfacedObject :

    utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var
      MonObjet : IMonObjet;
    begin
      MonObjet := TMonObjet.Create;
    end;
    déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    type
      IMonObjet = interface
        [{CTRL+G}]
        function GetInstance: IMonObjet;
     
        function GetA: integer;
        procedure SetA(value: integer);
     
        property A : integer read GetA write SetA;
      end;
     
      TMonObjet = class(TInterfacedObject, IMonObjet)
      private
        fA : integer;
        function GetA: integer;
        procedure SetA(value: integer);
      public
        function GetInstance: IMonObjet;
      end;
    explication :

    on utilise l'interface et non l'objet (IMonObjet donc).
    dans l'interface, il n'y a pas de constructeur, ni de destructeur (contrairement à TMonObjet).
    seul donc les méthodes de IMonObjet apparaitrons.
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  11. #11
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    Solution intéressante, je vais la creuser.
    Si je comprends bien la definition de TMonObjet devra être masquée dans le "implementation" (de mon unité par exemple).

    Par contre j'aurais mis le GetInstance() dans une classe utilitaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    TToolClass=class
    public
      class function GetMonObjetInstance():IMonObjet;
    end;
    .
    .
    .
    class function TToolClass.GetMonObjetInstance():IMonObjet;
    begin
    //...tests d'unicité de TMonObjet
      Result :=IMonObjet(TMonOjet.Create());
    end;
    Merci
    Pensons bien, pensons bio

  12. #12
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    L'usage d'une interface est effectivement une bonne solution pour masquer l'implémentation.

    Citation Envoyé par samaury
    Solution intéressante, je vais la creuser.
    Si je comprends bien la definition de TMonObjet devra être masquée dans le "implementation" (de mon unité par exemple).
    Tu comprends bien

    Voici un exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    (...)
    type
      IOutils = interface 
        function AjouteEntier(E1, E2: Integer): Integer;
        (...)
      end; 
     
    function Outils: IOutils; //fonction renvoyant la boite à outils
     
    implementation
     
    var
      GOutils: IOutils = nil;
     
    type
      TOutils = class(TInterfacedObject, IOutils)
      private
        function AjouteEntier(E1, E2: Integer): Integer;
      public
        constructor Create;
      end;
     
    function Outils: IOutils;
    begin
      if GOutils = nil then
        GOutils := TOutils.Create;
      Result := GOutils;
    end;
     
    { TOutils }
     
    function TOutils.AjouterEntier(E1, E2: Integer): Integer;
    begin
      // cette fonction déchire grave :)
      Result := E1 + E2;
    end;
     
    constructor TOutils.Create;
    begin
      // Logique du constructeur ici
    end;
     
    end.
    Akim Merabet

  13. #13
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    Tu comprends bien
    Me voila rassuré
    Merci
    Pensons bien, pensons bio

  14. #14
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 948
    Points
    3 948
    Par défaut
    Salut

    L'implémentation du singleton si l'on veut être formel n'est pas simple avec Delphi (je ne parle pas de la version .NET, je ne la connais pas).

    Le constructeur ne peut être privé car Create est toujours disponible depuis TObject et on ne peut pas réduire la portée d'une méthode. En outre, Delphi a ce petit défaut qu'il est toujours possible pour un développeur de libérer l'objet à tout moment.

    Pour le singleton, j'ai trouvé une solution "exotique" qui consiste à employer une classe et non un objet. Les méthode sont alors des méthodes de classe. L'état de "l'objet singleton" est représenté par des variables d'implémentation de son unité. Cela n'amène pas à un travail surhumain. Mais la solution a ses limites, l'état du singleton est en dehors (variables d'implémentation) de l'entité syntaxique utilisée, il n'est pas possible par exemple d'examiner l'état interne de ton objet grâce à un pointeur.

    C'est un peu de la bidouille, mais du fait de l'emploi d'une classe, on obtient bien un singleton. Chaque classe est unique par nature.
    Cependant si ton singleton

    Cdlt

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  15. #15
    Membre habitué Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Points : 141
    Points
    141
    Par défaut
    Merci pour ta remarque.
    J'ai implémenté la solution du Dr Who basée sur l'utilisation d'interface.
    Ca correspond bien à ce qu'il me fallait.
    @+
    Pensons bien, pensons bio

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Changer la visibilité d'un champ à partir d'un autre
    Par mounana199' dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 25/04/2014, 21h05
  2. Changer la visibilité d'un div avec un bouton
    Par Wnejla dans le forum Développement Web avec .NET
    Réponses: 1
    Dernier message: 29/04/2013, 22h33
  3. Edit : Div, changer la visibilité avec display
    Par Wookis dans le forum Général JavaScript
    Réponses: 18
    Dernier message: 19/08/2011, 10h40
  4. visibilité des variables d'un constructeur
    Par med_anis_dk dans le forum Langage
    Réponses: 4
    Dernier message: 06/05/2007, 21h07
  5. Réponses: 8
    Dernier message: 17/04/2007, 11h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo