Les classes sont comme les plans d’une maison. Vous pouvez en créer plusieurs à partir d’un plan. De la même manière, nous pouvons créer plusieurs objets à partir d’une classe.
Pour les classes, nous allons utiliser la lib: classic.
Cliquez sur classic.lua puis sur Raw et copiez le code
Allez dans votre éditeur de texte, créez un nouveau fichier classic.lua et coller le code.
Maintenant, nous avons besoin de l’appeler :
|
|
Nous sommes prêt pour créer des classes. Créez un nouveau fichier rectangle.lua et mettez-y le code suivant :
|
|
Tout sera expliqué ultérieurement. Mettez ce code dans votre main.lua
|
|
Quand vous lancez le jeu, vous devriez voir 2 nombres aléatoires s’afficher.
Examinons ce code étape par étape :
- Nous créons une nouvelle classe avec Rectangle = Object:extend(). Rectangle devient une classe. Ce sera notre plan/modèle. Contrairement aux propriétés, les classes sont généralement écrites avec un caractère majuscule sur la première lettre.
- Dans main.lua nous disons r1 = Rectangle(). Même si Rectangle est une table, nous pouvons encore l’appeler comme si c’était une fonction. Son fonctionnement sera pour un autre chapitre mais en appelant Rectangle(), cela crée une nouvelle instance. Cela signifie que notre plan est pris pour créer un nouvel objet avec toutes ses classes. Chaque nouvelle instance est unique.
- Pour prouver que r1 est unique, nous avons créer une autre instance appelé r2. Toutes les 2 ont la propriété test mais avec des valeurs différentes.
- Quand nous appelons Rectangle(), cela exécute Rectangle.new. C’est ce que l’on appelle un constructeur.
- Le paramètre self est l’instance que nous sommes en train de modifier. Si nous devions mettre Rectangle.test = math.random(0, 1000), nous donnerions la propriété au plan et non à une instance faite avec le plan. Faisons quelques changements à notre classe :
|
|
C’est comme l’objet rectangulaire en mouvement que nous avons fait au chapitre 8 sauf que cette fois nous mettons le code du mouvement et de la partie du dessin dans l’objet. Maintenant, il suffit d’appeler la mise à jour et de dessiner dans main.lua :
|
|
Quand vous lancez le jeu, vous devriez voir un rectangle bouger !
En fait, nous avons créé une classe appelée Rectangle. Nous avons créé une instance de cette classe appelé r1. Maintenant r1 a une fonction qui le met à jour (update) et qui le dessine (draw). Nous appelons ces fonctions et comme premier argument nous passons l’instance r1. C’est ce que le self devient dans les fonctions.
Cependant il est gênant de voir comment nous passons r1 à chaque appel d’une de ces fonctions. Heureusement, Lua a des raccourcis pour ça. Quand nous utilisons deux points (:), l’appel de fonction passera automatiquement l’objet à gauche des « : » comme premier argument :
|
|
Et nous pouvons le faire avec toutes les fonctions aussi :
|
|
Ajoutons quelques paramètres à Rectangle:new() :
|
|
Avec ça nous pouvons donner à r1 et r2 leur propre position et leur propre taille :
|
|
Donc maintenant, nous avons 2 rectangles en mouvement. C’est ce qui rend les classes géniales. r1 et r2 sont les mêmes mais ils sont uniques.
Une autre chose qui rend les classes géniales est l’héritage.
L’héritage
Avec l’héritage, nous pouvons étendre nos classes. En d’autres thermes, nous faisons une copie de notre plan et nous y ajoutons des fonctionnalités sans modifier l’original.
Faisons un jeu avec des monstres. Chaque monstre a sa propre attaque et se déplace différemment mais ils peuvent subir des dommages et peuvent mourir. Les fonctionnalités se chevauchant devraient être placées dans une super classe ou une classe de base. Elles fournissent les fonctionnalités que tous les monstres ont en commun. Ensuite la classe de chaque monstre peut étendre la superclasse et y ajouter ses propres caractéristiques.
Créons une nouvelle forme mobile, le cercle. Qu’auront en commun notre rectangle et notre cercle ?
Hé bien, ils se déplaceront tous les deux donc faisons une superclasse pour nos 2 formes.
Créez un nouveau fichier appelé shape.lua et mettez-y le code suivant :
|
|
Notre superclasse Shape gère maintenant le mouvement. Je devrais souligner que notre superclasse est juste un terme. “A est une superclasse de B”. Une superclasse est toujours la même chose qu’une autre classe. C’est juste la manière de l’utiliser qui est différente.
Quoi qu’il en soit, nous avons maintenant une superclasse qui gère nos mouvements. Nous pouvons faire de Rectangle une extension de Shape et supprimer sa mise à jour :
|
|
Avec Rectangle = Shape:extend() nous avons créé Rectangle qui est une extension de la superclasse Shape.
Shape a sa propre fonction appelée :new(). En créant Rectangle:new(), nous annulons la fonction d’origine. Cela veut dire que quand nous appelons Rectangle(), cela n’exécutera pas Shape:new() mais plutôt Rectangle:new().
Mais rectangle a la propriété super, donc la classe Rectangle est étendu. Avec Rectangle.super nous pouvons accéder aux fonctions de la superclasse et nous l’utilisons pour appeler Shape:new().
Nous devons nous même lui passer self comme premier argument et ne pas laisser Lua le gérer avec les deux points (:) parce que nous n’appelons pas la fonction comme une instance.
Maintenant, nous devons créer une classe cercle. Créez un nouveau fichier appelé circle.lua et mettez-y le code suivant :
|
|
Donc nous faisons de Circle une extension de Shape. Nous passons x et y à new(), la fonction de Shape avec Circle.super.new(self, x, y).
Nous donnons à notre classe Circle sa propre fonction de dessin. C’est ainsi qu’on dessine un cercle. Les cercles n’ont pas besoin de largeur ou de hauteur mais plutôt d’un rayon.
Et maintenant, dans main.lua chargeons shape.lua et circle.lua puis changeons r2 en un cercle :
|
|
Quand vous lancez le jeu, vous voyez bouger un rectangle et un cercle.
Encore quelques choses
Examinons ce code encore une fois.
- Nous chargeons la lib classic avec require “classic”. Le chargement de cette lib retourne une table que nous stockons dans un objet. Il est essentiel de simuler une classe car Lua n’a pas de notion de classe mais en utilisant la lib classic nous obtenons une très belle imitation d’une classe.
- Ensuite nous chargeons shape.lua. Dans ce fichier, nous créons une nouvelle classe appelée Shape. Nous l’utiliserons comme superclasse pour Rectangle et Circle. Les 2 choses que ces classes ont en commun sont les propriétés x et y ainsi que le mouvement horizontal. Ces similitudes sont celles que nous mettons dans Shape.
- Ensuite, nous créons la classe Rectangle. Nous en faisons une extension de la superclasse Shape. Dans la fonction :new(), le constructeur, nous appelons le constructeur de notre superclasse avec Rectangle.super.new(self, x, y). Nous passons self comme premier argument de sorte que Shape utilisera l’instance de notre plan et non pas celui du plan lui-même. Nous donnons à notre rectangle des propriété de largeur (width) et de hauteur (height) ainsi qu’une fonction de dessin.
- Ensuite, nous répétons ce qui précède à l’exception du cercle. À la place de la largeur et de la hauteur nous donnons la propriété rayon.
- Maintenant que nous avons nos classes de prêtes, nous pouvons commencer à créer des instances de ces classes. Avec r1 = Rectangle(100, 100, 200, 50) nous créons une instance de notre classe Rectangle. C’est un objet créer à partir de notre plan et non le plan lui même. Tout changement sera vrai pour cette instances mais n’affectera pas la classe. Nous mettons à jour cette instance, la dessinons et pour ça nous utilisons les deux points (:). C’est parce que nous avons besoin de passer notre instance comme premier argument et les deux points disent à Lua de le faire pour nous.
- Finalement nous faisons de même pour r2 sauf que nous en faisons un cercle.
Confus ?
Ça fait beaucoup d’informations en un seul chapitre et je peux imaginer que vous puissiez avoir du mal à tout comprendre.
Mon conseil: continuez à suivre les tuto. Si vous êtes nouveau dans la programmation il vous faudra du temps avant d’intégrer ces nouveaux concepts. Je continuerai à ajouter des explications sur les anciens sujets sans oublier les récents.
Résumé
Les classes sont comme des plans. Nous pouvons créer de multiples objets à partir d’une classe. Pour simuler une classe, nous utilisons la lib classic.
Vous créez une classe avec le nom ClassName = Object:extend(). Vous créez une instance de la classe avec instanceName = ClasseName(). Cela appellera la fonction ClassName:new(). Ceci est appelé le constructeur. Chaque fonction de la classe devrait commencer avec le paramètre self de sorte que lorsque vous appelez la fonction, vous puissiez passez l’instance comme premier argument: instanceName.functionName(instanceName). Nous pouvons utiliser les deux points (:) pour dire à Lua de le faire à notre place.
Nous pouvons étendre une classe avec ExtensionName = ClassName:extend(). Cela fait de ExtensionName, une copie de ClassName à laquelle nous pouvons ajouter des propriétés sans modifier ClassName. Si nous donnons à ExtensionName une fonction que ClassName possède déjà, nous pouvons toujours appeler la fonction d’origine avec ExtensionName.super.functionName(self)