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

Discussion: POO et Héritage

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur Autodidacte
    Inscrit en
    janvier 2008
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Autodidacte

    Informations forums :
    Inscription : janvier 2008
    Messages : 40
    Points : 31
    Points
    31

    Par défaut POO et Héritage

    Bonjour

    Je tente de faire de la pseudo POO en langage Lua. Voici comment je déclare mes classes:

    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
     
    --Classe Chien
     
    --Métatable
    mt_chien = {}
     
    --Constructeur
    function Chien(age)
      return setmetatable({
        m_age = age
      }, mt_chien)
    end
     
    --Fonctions membres
    function mt_chien.__index(o, c)
      if c == "lireAge" then
        return function()
          return o.m_age
        end
      elseif c == "vieillir" then
        return function()
          o.m_age = o.m_age + 1
        end
      end
    end
     
    --Utilisation
    rex = Chien(3)
    print("Rex a "..rex.lireAge().." ans")
    rex.vieillir()
    print("Rex a vieillit, il a maintenant "..rex.lireAge().." ans")
    Cela fonctionnait très bien jusqu'au moment où j'ai eu besoin du concept d'héritage. Je n'arrive pas à hériter une classe d'une autre avec ce code. Je sais que l'héritage est possible en Lua et j'ai lu plusieurs tutoriels sur le sujet, mais les classes sont construites de façon bien différente dans ces tutoriels et je n'arrive pas à les comprendre.

    J'aimerais que quelqu'un m'explique comment hériter une classe d'une autre avec mon code si c'est possible. Sinon, pourriez-vous me dire quelle est la bonne façon de créer une classe qui permet l'héritage et pourquoi?

    Merci

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Développeur Autodidacte
    Inscrit en
    janvier 2008
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Autodidacte

    Informations forums :
    Inscription : janvier 2008
    Messages : 40
    Points : 31
    Points
    31

    Par défaut

    Petite mise à jour...
    J'ai trouvé ceci:

    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
    --Classe Félin
     
    Felin = {}
     
    --Constructeur
    function Felin.Instancier()
      return setmetatable({},{__index = Felin})
    end
     
    --Fonction membre
    function Felin.Identifier()
      print("Je suis un félin")
    end
     
    --Classe Chat
     
    Chat = {}
     
    --Constructeur
    function Chat.Instancier()
      return setmetatable({}, {__index = Chat})
    end
     
    --Relation d'héritage
    setmetatable(Chat, {__index = Felin})
     
    --Fonction membre substituée
    function Chat.Identifier()
      Felin.Identifier()
      print("Je suis également un chat")
    end
     
    --Utilisation
     
    felin = Felin.Instancier()
    felin.Identifier()
     
    minou = Chat.Instancier()
    minou.Identifier()
    La technique d'héritage est assez facile à comprendre. Les fonction de la classe mère font partie de la métatable de la classe fille. Pour en substituer une de la classe mère, il suffit de la déclarer dans la table de la classe fille car l'ordinateur ira chercher un élément dans la métatable (classe mère) seulement si il ne la trouve pas dans la table (classe fille).

    Ce code fonctionne, mais il pose un gros problème. Comment faire pour ajouter des variables membres et surtout, comment faire pour y accéder depuis une fonction membre.

    Il y a aussi le "constructeur" que je n'aime pas car c'est une fonction de la table. Je préfèrerais créer un objet en utilisant seulement le nom de la classe comme une fonction. J'ai essayé avec la métaméthode "__call", mais ça ne fonctionne pas avec ce code.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Classe = {}
     
    --Le problème est ici
    setmetatable(Classe, Classe)
     
    function Classe.__call(o, ...)
      print("La table a été utilisée comme une fonction")
    end
     
    Classe()
    Bon ça ce n'est pas très important, ce qui est indispensable c'est l'ajout de variables membres de la classe et l'accès de celles-ci par l'intermédiaire des fonctions membres. Je n'y arrive pas. Si vous avez une idée, elle sera la bienvenue...

  3. #3
    Membre régulier
    Homme Profil pro
    Ing. Hydraulicien
    Inscrit en
    août 2012
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Burkina Faso

    Informations professionnelles :
    Activité : Ing. Hydraulicien
    Secteur : Enseignement

    Informations forums :
    Inscription : août 2012
    Messages : 26
    Points : 71
    Points
    71

    Par défaut

    Bonsoir Cbelfun,

    Définir l'héritage en Lua peut se faire de manière assez simple. Je peux faire une proposition minimale à partir de laquelle il te sera simple d'ajouter de nouvelles fonctionnalités.

    Nous allons commencer par définir une petite fonction qui nous permettra d'exploiter nos classes comme des fonctions.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    local function call(class,...) return class:new(...) end
    La fonction ainsi définie appelle le constructeur de classe (méthode new) en lui passant tous les arguments qu'elle reçoit. Nous allons implémenter ce constructeur par la suite.

    Ensuite, nous pouvons définir un code minimal qui nous produit une classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    local function class()
      local new_class = {} -- crée la nouvelle classe
      local newclass_mt = {__index = new_class} -- crée une métatable, qui pointe vers la classe new_class
     
      function new_class:new() -- constructeur de classe, qui retourne une instance de classe
        local instance = {}
        return setmetatable(instance, newclass_mt) -- définit une métatable pour l'instance.
      end
     
      return setmetatable(new_class, {__call = call}) -- pour pouvoir appeler la classe comme une fonction.
    end
    Nous disposons donc du nécessaire pour produire des classes et des instances de classe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Felin = class()
    felin = Felin() -- identique à Felin:new()
    Nous allons maintenant modifier la fonction précédente afin de pouvoir produire une classe qui hérite d'une superclasse. L'idée étant que la sous classe est aussi une classe, mais qui a sa métatable lui indiquant d'aller chercher dans sa superclasse.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    function class(super_class)
        local subclass = {}
        local subclass_mt = {__index = new_class}
     
        function subclass:new()
            local instance = {}
            setmetatable(instance, subclass_mt)
            return instance
        end
     
        return setmetatable(subclass, {__index = super_class, __call = call})
    end
    Ainsi donc, si l'on passe une classe en tant qu'argument à la fonction, elle produit une sous classe. Si par contre on ne lui passe rien, nil, elle retourne tout simplement une classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    local Felin = class() -- une classe sans superclasse
    local Chat = class(Felin) -- une sous-classe de la classe Felin
    print(Felin()) -- une instance de la classe Felin
    print(Chat()) -- une instance de la classe Chat
    A titre d'information, il existe pas mal de librairies Orienté-Objet pour Lua, dont 30log, dont je suis l'auteur. Il est possible qu'elle puissent te simplifier grandement la tâche.

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Développeur Autodidacte
    Inscrit en
    janvier 2008
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Autodidacte

    Informations forums :
    Inscription : janvier 2008
    Messages : 40
    Points : 31
    Points
    31

    Par défaut

    Merci pour ta réponse Roland_Y

    Entre temps j'ai trouvé une façon de faire qui fonctionne et que j'aime bien et j'ai réussi à utiliser la métaméthode __call pour instancier les classes en m'inspirant de ton 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
    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
    --Classe Entité
     
    Entite = {}
     
    --Constructeur
    setmetatable(Entite, {
      __call = function(self, sante)
        t = {}
        setmetatable(t, self)
        self.__index = self
        t.m_sante = sante or 1
        return t
      end
    })
     
    --Fonctions membres
    function Entite.deplacer()
      print("Je marche")
    end
     
    function Entite:lireSante()
      return self.m_sante
    end
     
    --Classe Humain
     
    Humain = {}
     
    --Relation d'héritage
    setmetatable(Humain, {__index = Entite,
      --Constructeur
      __call = function(self, sante, nom)
        t = Entite(sante)
        setmetatable(t, self)
        self.__index = self
        t.m_nom = nom or "sans nom"
        return t
      end
    })
     
    --Fonctions membres
    function Humain.parler()
      print("Je parle")
    end
     
    function Humain:lireNom()
      return self.m_nom
    end
     
    --Classe Oiseau
     
    Oiseau = {}
     
    --Relation d'héritage
    setmetatable(Oiseau, {__index = Entite,
      --Constructeur
      __call = function(self, sante)
        t = Entite(sante)
        setmetatable(t, self)
        self.__index = self
        return t
      end
    })
     
    --Fonction membre substituée
    function Oiseau.deplacer()
      print("Je vole")
    end
     
    --Utilisation
     
    print("Utilisation de la classe Entité:")
    etre = Entite(5)
    etre.deplacer()
    print("Ma sante est "..etre:lireSante())
     
    print("Utilisation de la classe Humain:")
    homme = Humain(10, "Roger")
    print("Bonjour, je m'appelle "..homme:lireNom())
    homme.parler()
    homme.deplacer()
    print("Ma sante est "..homme:lireSante())
     
    print("Utilisation de la classe Oiseau:")
    animal = Oiseau(3)
    animal.deplacer()
    print("Ma sante est "..animal:lireSante())
    Ce code me convient, je vais donc attribuer la mention "Résolu" à cette conversation. Je reviendrai voir de temps en temps au cas où quelqu'un aurait un commentaire à ajouter.

    Merci

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

Discussions similaires

  1. [POO/Template] Héritage de paramètre template.
    Par méphistopheles dans le forum Langage
    Réponses: 9
    Dernier message: 18/11/2008, 19h02
  2. [POO] Opérateurs & Héritage
    Par Haknaton dans le forum C++
    Réponses: 3
    Dernier message: 05/10/2008, 23h47
  3. [Prototype] [POO] L'héritage
    Par diva_69 dans le forum Bibliothèques & Frameworks
    Réponses: 7
    Dernier message: 04/12/2007, 12h05
  4. [POO] VB6 --> héritage
    Par tigrou2405 dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 31/08/2007, 21h29
  5. [POO] Problème héritage des classes PHP4
    Par zana74 dans le forum Débuter
    Réponses: 2
    Dernier message: 15/08/2006, 17h00

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