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

Macros et VBA Excel Discussion :

Faire de la POO en VBA


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 128
    Par défaut Faire de la POO en VBA
    Bonjour à tous !

    Comme le sujet l'indique, je suis confronté à un problème de POO en VBA. Vous allez dire: mais pourquoi voudrai-je faire de la POO alors que le VBA n'est pas vraiment destiné à ça ? Et bien figurez vous que j'en ai besoin

    Le soucis c'est que, dans mon module de classe, je déclare mes attributs en private et je les récupère grâce aux Proterty Let/Get.
    Mais de base, elles sont publiques, donc dans n'importe quel module (classique) on peut venir modifier les champs de mon objet. Mais j'ai pas envie qu'un utilisateur puisse venir modifier ou accéder aux champs comme il le souhaite.

    Du coup j'ai pensé à déclarer mes Proterty en private (pour qu'elles ne soient accessibles que dans le module de classe) et de créer mes propres fonctions qui permettent ou non d’accéder aux property.

    Voici un exemple de code:
    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
     
    'module de classe: voiture
     
    Private couleur As String
    Private marque As String
     
     
     
    Private Property Let LetCouleur(pCouleur As String)
        couleur = LCase(pCouleur)
    End Property
     
    Private Property Let LetMarque(pMarque As String)
        marque = LCase(pMarque)
    End Property
     
     
    Private Property Get GetCouleur()
        GetCouleur = couleur
    End Property
    Private Property Get GetMarque()
        GetMarque = marque
    End Property
     
    ' fonction que je veux definir pour pas que l'utilisateur fasse ce qu'il veut !
    Public Function afficherVoiture() As String
        afficherVoiture = "marque: " & Me.GetMarque() & " / couleur: " & Me.GetCouleur
    End Function

    Là, dans l'exemple, je veux définir la manière donc l'utilisateur pour récupérer la valeur des attributs d'un objet voiture.
    Mais en passant par Private Property, la fonction afficherVoiture n'a plus accès aux Property ! Alors qu'elle est dans le même module (de classe).
    (PS: si je laisse Property en public ça marche, mais c'est aussi accessible dans n'importe quel autre module)

    Savez-vous comment je peux faire pour déclarer mes Property en Private dans mon module de classe et CONTINUER d'y avoir accès en RESTANT dans le module de classe ?

    Merci !
    Slooby.

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 723
    Par défaut
    Bonjour,

    Pourquoi mets-tu les Get en Private?

    Si tu veux te protéger des modifs non maîtrisées, c'est seulement sur les Let que c'est nécessaire.

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations forums :
    Inscription : Décembre 2012
    Messages : 129
    Par défaut
    A mon avis c'est plutot ça que tu veux faire ?

    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
     
    Private cCouleur As String
    Private cMarque As String
     
     
     
    Public Property Let couleur(pCouleur As String)
        cCouleur = LCase(pCouleur)
    End Property
     
    Public Property Let marque(pMarque As String)
        cMarque = LCase(pMarque)
    End Property
     
     
    Private Function GetCouleur()
        GetCouleur = cCouleur
    End Function
    Private Function GetMarque()
        GetMarque = cMarque
    End Function
     
    ' fonction que je veux definir pour pas que l'utilisateur fasse ce qu'il veut !
    Public Function afficherVoiture() As String
        afficherVoiture = "marque: " & GetMarque() & " / couleur: " & GetCouleur
    End Function
    Ensuite tu peux utiliser ton objet simplement comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Dim a As Classe1
     
    Set a = New Classe1
    a.couleur = "rouge"
    a.marque = "206"
     
    MsgBox a.afficherVoiture

  4. #4
    Membre expérimenté
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 128
    Par défaut
    Promethee: La protection des Get est tout aussi importante que les Get. Imagine que, pour une carte de credit, n'importe qui puisse faire un Get Code il faut mieux redéfinir qui peut ou peut pas accéder aux Let/Get.

    mathspoundz: NON absolument pas. Je veux bien les mettre en PRIVATE. Car comme tu l'as écrit, tout le monde peut accéder aux attributs ! (CF: voir l'exemple précédent de la carte bancaire )


    Mais sinon, après moulte tuto et pleins de tests, j'ai presque trouvé la solution.
    Je retourne dessus quand j'aurais fini mes autres projets et je vous tient au courant pour la solution !

    (PS: l'idée de tout mettre en private est bel et bien de décider quand et comment on peut accéder aux attributs. Par exemple, une personne a un nom, un prenom, une taille et une carte de crédit à son nom. Le Nom et le Prénom doivent être accessibles en écriture UNIQUEMENT à sa création, alors que la taille peut être modifiée tout le temps. Et la carte de crédit peut etre LUE UNIQUEMENT par la banque !
    Dans cet exemple, on voit bien qu'il est tout aussi IMPORTANT de protéger les Let que les Get)

    A bientôt !
    Slooby

  5. #5
    Membre Expert
    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 723
    Par défaut
    On passe de la couleur de la voiture au code de carte bleue... => Ta réponse n'est pas cohérente avec ton exemple puisque tu crées justement une fonction permettant de lire ces valeurs même s'il s'agit d'un print préformatté et non d'un accès direct. Explique-moi où est la sécurité en lecture...

    Tu refuserais donc un GetCodeCarteBleue public mais pas un AfficherCodeCarteBleue? :p

  6. #6
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations forums :
    Inscription : Décembre 2012
    Messages : 129
    Par défaut
    +1 pour moi un private get est absurde. C'est bien un private function que tu veux.

    Par essence les Get et les Let sont justement les interfaces entre l'objet et l'utilisateur.

    Dans mon exemple essai de faire a.couleur ou a.cCouleur ou a.getCouleur, aucun ne fonctionne. Ta couleur est donc bien protégée, et accessible via print formaté gràce à le méthode publique "afficherCouleur"

  7. #7
    Membre Expert
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 725
    Par défaut
    Promethee: La protection des Get est tout aussi importante que les Get. Imagine que, pour une carte de credit, n'importe qui puisse faire un Get Code il faut mieux redéfinir qui peut ou peut pas accéder aux Let/Get.
    La on rentre dans un concept de DesignPattern !

    Ce que tu évoque est alors le DesignPattern Proxy

    Mais sur du VBA là après on va loin

    Et si tu est en train de faire une application bancaire avec Excel et VBA => Arrête tout de suite

  8. #8
    Membre Expert
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 725
    Par défaut
    Encore une fois on est sur du DesignPattern, dans le cas que tu évoque maintenant il s'agirait plutôt du coup d'un pattern Factory !

    Et ta méthode creerVoiture devrait en réalité être static !
    Elle ne doit pas dépendre d'une instance, ça n'as absolument aucun sens
    Ce qui du coup empêcherai de la rappeler (comme tu peux le faire, même si ça ne fais rien) sur un objet instancié !

    Et puis pour une voiture on est d'accord qu'on changera pas sa marque ou son modèle une fois qu'elle est fabriqué mais sa couleur par contre peux sans problème être modifié !

  9. #9
    Membre expérimenté
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 128
    Par défaut
    Citation Envoyé par cerede2000 Voir le message
    Encore une fois on est sur du DesignPattern, dans le cas que tu évoque maintenant il s'agirait plutôt du coup d'un pattern Factory !

    Et ta méthode creerVoiture devrait en réalité être static !
    Elle ne doit pas dépendre d'une instance, ça n'as absolument aucun sens
    Ce qui du coup empêcherai de la rappeler (comme tu peux le faire, même si ça ne fais rien) sur un objet instancié !

    Et puis pour une voiture on est d'accord qu'on changera pas sa marque ou son modèle une fois qu'elle est fabriqué mais sa couleur par contre peux sans problème être modifié !

    Exact, on est dans un cas de DesignPattern. Chose assez folle à faire en VBA

    la ligne de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Dim v1 As New voiture
    Set v1 = v1.creerVoiture("verte", "bmw")
    est horrible à écrire, Set v1=v1... c'est vraiment pas super .... Mais j'ai pas encore réussi à faire mieux.

    En POO (du genre en JAVA) ça passerai tout seul avec un constructeur, mais là je n'y arrive pas encore.
    Il faudrait un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Dim v1 As Voiture
    Set v1 = creerVoiture(parametre1, parametre2)
    mais même si la méthode est PUBLIQUE, si je ne l'applique pas directement à une instance de voiture ( uneInstanceVoiture.creerVoiture(..,..) alors l'éditeur ne reconnait pas la méthode

    Du coup c'est pour ça que j'ai cette horrible écriture.
    Si t'as une solution pour passer par une méthode static je suis prenneur

    Slooby.

  10. #10
    Membre éclairé
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 35
    Par défaut PublicNotCreatable
    Bonjour,

    dans n'importe quel module (classique) on peut venir modifier les champs de mon objet
    Oui et non!

    Il y a la portée Friend pour les propriétés et méthodes objets.
    Un module de classe (dans VBA) peut avoir 2 portés:
    - Private (par defaut) : accessible uniquement à l'intérieur de ton projet
    - PublicNotCreatable : visible depuis un autre projet, par contre impossible de créer l'objet depuis un autre projet (utilisation de New impossible), du coup il faut créer un fonction constructeur dans le projet pour qu'il puisse être utilisé

    Ton objet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Option Explicit
     
    Public Property Let Para1(Val As String)
    'Visible par tout le monde dans ton projet
    'Si l'objet est PublicNotCreatable alors cette propriété est visible également à l'extérieur
    'Sinon l'objet n'est pas visible du tout
    End Property
     
    Friend Property Let Para2(Val As String)
    'Visible par tout le monde dans ton projet
    'Si l'objet est PublicNotCreatable alors cette propriété n'est pas visible depuis l'extérieur
    'Sinon l'objet n'est pas visible du tout
    End Property
    Dans un module de code :

    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
    Public Sub TonCode()
     
        Dim v As Voiture
        Set v = CreatorVoiture("Pagio", "Ranaud")
     
    End Sub
     
    Public Function CreatorVoiture(Para1 As String, Para2 As String) As Voiture
    'Si Voiture est PublicNotCreatable il faut absolument prévoir une fonction dans un module standard
    'qui est capable de retourner une nouvelle instance de voiture
        Dim Result As Voiture
        Set Result = New Voiture
     
        Result.Para1 = Para1
        Result.Para2 = Para2
     
        Set CreatorVoiture = Result
     
    End Function
    PS:
    Pour les modules standard, ils sont par défaut Public et donc visible depuis l'extérieur.
    Mais il est possible de les rendre privé : il faut mettre tout en haut du module Option Private Module

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

Discussions similaires

  1. [XL-2010] Comment faire du File Mapping en VBA
    Par pikron dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 26/07/2013, 12h51
  2. [XL-2007] Comment faire pour piloter internet en VBA depuis EXCEL ?
    Par Debutant10 dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 17/08/2012, 18h17
  3. Comment faire un fichier "Aide" en VBA ?
    Par NEC14 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 12/01/2009, 10h28
  4. Quel EDI pour faire de la POO ?
    Par lolymeupy dans le forum Zend Studio
    Réponses: 1
    Dernier message: 09/07/2008, 19h15
  5. Comment faire Copier/Coller par code VBA sur INTERNET...
    Par GESCOM2000 dans le forum Access
    Réponses: 5
    Dernier message: 02/01/2006, 13h19

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