Fast Ruby n°2

10 Réponses • 1396 Vues

Nuri Yuri

HostMaster

Fast Ruby n°2 - Les modules et classes en tant que conteneur

Avant d'attaquer la programmation, nous allons parler d'une utilisation des classes et module vis à vis des constantes.
Déjà il faut savoir qu'une classe ou qu'un module lorsqu'ils sont définit par le mot clef class ou module doivent obligatoirement avoir un nom qui correspond en réalité à la définition d'une constante. (Majuscule au début.)

Pour faire simple, c'est comme si vous créez un objet du type Classe ou un objet du type Module dans une constante, et l'intérêt de ces objets en plus de servir de générateur d'objet ou de conteneur à fonctions c'est aussi de servir de conteneur à constante.


Pourquoi stocker les constantes dans des classes ou des modules ?


L'intérêt de faire ça est d'organiser le programme de manière logique. Quand vous utilisez un ordinateur personnel (PC / MAC) l'OS vous organise par défauts les documents de cette façon :
Utilisateur + Documents (pour les documents quelconques)
  |
  + Téléchargement (pour ce que vous téléchargez via internet)
  |
  + Images (pour vos photos et images)
  |
  + Musiques (pour "vos" musiques)
  |
  + Videos (pour vos vidéos)
Cette organisation n'est pas un hasard et a un but précis : Mieux vous y retrouver dans ce que vous utilisez sur l'ordinateur. Pour un programme Ruby, c'est tout aussi important.

Organiser le programme en "dossier / fichiers" permet de gagner en performance (plus facile de trouver une constante parmi quelques unes que parmi des milliers) et d'avoir un programme relativement propre et logique.

Par exemple, il y a un module Math dans Ruby, ce module Math contient deux constantes importante en Maths : pi et e
Pour y accéder il suffit de faire Math::PI et Math::E. Il en va de même pour le module Complex (Ruby 1.9 +) qui contient le nombre i en tant que constante : Complex::I
[bgcolor=#000000]Yuki.N>Math::E
2.718281828459045
Yuki.N>Math::PI
3.141592653589793
Yuki.N>Complex::I
0+1i
[/bgcolor]

Il faut comprendre que ces constantes n'ont pas pour unique utilité d'être des constantes qui sont là pour le Lulz, comme dit dans le précédent tutoriel, elles servent à définir des objets qui seront utilisés plusieurs fois au long du programme et qui pourraient changer au cours du développement, ça permet entre autre d'éviter d'avoir à chercher tous les endroits qui ont besoin d'une modification, ça sera fait par le biais de la constante en question.

Dans PSP, plusieurs constantes sont stockés dans le module POKEMON_S, EXP_TABLE par exemple qui doit être corrigée sur la plupart des kits à cause d'une erreur dans la courbe erratique. Heureusement qu'il y a cette constante, imaginez si vous aviez à chercher le calcul de la courbe erratique dans la classe Pokemon ?
Dans Pokémon SDK on a une application plus concrète de cela :
  • Tous les objets de donnée statique du jeu sont stockés dans le module GameData, ainsi les données Pokédex d'un Pokémon c'est du GameData::Pokemon
  • Tous les objets servant à faire fonctionner le jeu en temps réel (calculs etc...) sont stockés dans le module PFM, ainsi pour créer un Pokémon on peut faire PFM::Pokemon.new(id, level, shiny, non_shiny) et nous avons un Pokémon prêt à être utilisé in Game.
  • Toutes les interfaces affichés à l'écran sont dans le module GamePlay.
  • Tous les systèmes un peut particuliers comme le FollowMe, les particules, les teintes de l'écran sont stockés dans le module Yuki
  • Les index d'interrupteur sont stockés dans le module Sw du module Yuki, si on veut l'id de l'interrupteur qui active le Pokedex il suffira d'écrire là où l'on veut l'interrupteur : Yuki::Sw::Pokedex et nous obtiendrons par défauts 100. Si le maker décide qu'il veut pas l'interrupteur 100 pour ça mais le 8, il aura juste à aller dans le script Yuki::Sw et modifier ce qui se trouve derrière Pokedex =, les scripts fonctionneront toujours aussi bien et aucuns bugs ne sera provoqué à cause de ça. (Cela dit si il a déjà utilisé l'interrupteur dans ses évents il se peut que ses évents ne fonctionnent pas correctement.)

Bien entendu le but est d'avoir une organisation propre du système, il faut savoir que pour un jeu vidéo les dépendances entre objet et systèmes sont énormes alors il faut faire en sorte à ce qu'elles soient facilement maintenable, si vous passez un quart d'heure à changer une valeur qui est utilisé à plusieurs endroits dites vous qu'il y a un léger problème dans ce que vous utilisez.


Comment Ruby accède aux constantes ?


Après tout le blabla de la partie précédente, je vais vous indiquer comment Ruby accède aux constantes en donnant des règles.

Règle n°1 : Si le nom d'une constant est écrit sans rien devant (pas de :: devant).
Ruby va chercher la constante dans la classe ou le module à l'endroit où le nom de la constante a été mentionné. Si vous appelez une constante dans une méthode définit dans une certaine classe, Ruby va chercher la constante dans la certaine classe, même si la méthode est hérité dans une classe enfant.
  • Si la constante n'est pas trouvée, dans le cas où la constante n'est pas trouvée, Ruby va chercher la constante dans les classes parentes. (Les modules n'ont pas de parents.)
  • Si la constante n'est pas trouvée dans les parents, à ce moment là Ruby va chercher la constante dans la classe Object.
  • Si Ruby n'a toujours pas trouvé, une erreur de script (NameError) est levée par Ruby.
Pour illustrer cette règle, voici ce qui se passe pour ces deux récupérations de constante :

class Interface
  A = 5
  def constante_a
  A
  end
end

class Scene < Interface
  A = 66
  def initialize
  @b = String.new
  end
end

scene = Scene.new
print scene.constante_a
Lorsque le script entre dans la méthode initialize de la classe Scene, il va chercher la constante String :
  • Je suis dans la classe Scene, je cherche String...
    Je ne trouve pas, passons à la classe Interface (parent).
  • Je suis dans la classe Interface, je cherche String...
    Je ne trouve pas, passons à la classe Object (parent dans ce cas, mais pour un module ce n'est pas un parent).
  • Je suis dans la classe Object, je cherche String...
    Trouvé ! Je retourne donc l'objet en question ainsi il pourra être utilisé.
Lorsque le script passe sur print scene.constante_a il affichera 5 et non 66 car constante_a est définie dans Interface donc Ruby va chercher les constantes dans Interface. (Il se passe le même processus pour trouver la méthode constante_a en fait.)

Règle n°2 : Quelque chose est écrit devant le nom de la constante, le mot clef :: qui est en fait l'équivalent du / pour nos systèmes d'exploitation.
  • Si quelque chose est écrit avant le mot clef ::, et que c'est une constante, Ruby va chercher la constante selon la règle n°1 pour chercher ce qui est écrit après le mot clef :: selon la règle n°1 en utilisant ce qui est écrit devant le mot clef :: comme point de départ.
  • Si quelque chose est écrit avant le mot clef ::, et que c'est une variable, Ruby var prendre comme point de départ l'objet contenu dans la variable.
Attention, ce qui se trouve devant le mot clef :: doit toujours être un objet de type Class ou Module !
Exemple :
class A
  class B
  class C
  D = 5
  end
  end
  $B = B
end

print A::B::C::D
print $B::C::D
Pour « print A::B::C::D » il va se passer ceci :
  • Recherche de A... Trouvé, A est le nouveau point de recherche.
  • Recherche de B dans A... Trouvé ! B est le nouveau point de recherche.
  • Recherche de C dans B... Trouvé ! C est le nouveau point de recherche.
  • Recherche de D dans C... Trouvé ! Retour de l'objet contenu dans D.
Pour « $B::C::D » il va se passer ceci :
  • Recherche de C dans l'objet contenu dans $B. Trouvé ! C est le nouveau point de recherche.
  • Recherche de D dans C. Trouvé ! Retour de l'objet contenu dans D.
Comme vous pouvez le constater il y a moins d'étapes pour l'utilisation de la variable, mais attention c'est un leurre ! Il faut déjà que Ruby trouve $B et ceci peut être plus ou moins long donc je déconseille d'utiliser la méthode des variables qui n'est pas toujours très recommandable.

Règle n°3 : Extension de la deuxième règle mais pour le cas où rien est écrit devant le mot clef ::.
Ruby va partir de la classe Object pour chercher la constante.
Si on reprend notre code d'avant mais qu'on étend la classe A de cette manière :
class A
  def math
  ::Math
  end
  def b
  ::B
  end
  def b_fonctionnel
  A::B
  end
end

obj = A.new
p obj.math
p obj.b_fonctionnel
p obj.b
Pour ce script, « p obj.math » vas afficher Math, « p obj.b_fonctionnel » va afficher A::B et « obj.b » va provoquer une erreur car B n'est pas défini dans Object (pour notre code).

Voilà, je pense avoir tout dit sur les accès de constante et l'utilisation qu'on peut en faire, je pense que l'on pourra attaquer la programmation sur Ruby maintenant que les bases sont posés vis à vis des variables.

« Modifié: 08 mars 2015, 12:42:23 par Nuri Yuri »

ln(yo) = <3

Tuto Script

Comment ça personne n'a répondu encore ? '^'
Peut être (comme on l'a dit sur le chat), que c'est soit parce qu'il n'y a pas assez de personne motivées pour apprendre le ruby qu'il n'y a pas beaucoup de retour. Ou soit les personnes motivées ont du mal avec la manière de présenter les chose comme un cours classique, auquel cas il faudrait trouver une forme de tuto pour faire passer ça de manière ludique '^'

Bref, personnellement je trouve que c'est un bon tuto assez détaillé mais pas trop à la porté de n'importe qui d'un petit peu motivé pour apprendre :3
Très instructif, merci Yuri.
J'espère voir un petit cours sur les fenêtres, les bitmaps et WIN32API (a)

Nuri Yuri

HostMaster

Ça peut être intéressant, je vais y réfléchir :3
(Je l'appellerais probablement pas fast ruby vu que ça nécessite un peu plus que les notions de ruby :d)
ln(yo) = <3
Pour moi c'est du japonais !
J'essaye de comprendre mais ...

Rhenaud the Lukark

Programmeur

Olala le up ! Évite ça mec, un up de 2 mois c'est chaud :c

Est-ce que t'as lu le Fast Ruby 1 d'abord ? :perv:
Allez, je vais vous électriser avec ma musique de fou ! Tous en boite, va y avoir de l'électricité dans l'air ! o/
Malheureusement ce compte est plus ou moins décédé, mais si vous voulez me contacter, allez sur Discord (RhenaudTheLukark#4797) ou contactez moi via ma boite mail!

Nuri Yuri

HostMaster

Faudra que je pense à faire les autres.
Si tu ne comprends pas dis moi les points qui ne sont pas bien compris '^'
ln(yo) = <3
Yuri tu expliques bien mais je comprend pas je que veut dire "classe" .
Yuri tu expliques bien mais je comprend pas je que veut dire "classe" .

Quand tu code, tu dois le faire avec Class :ahde:

(Blague de programmeur, je suis drôle)

Nuri Yuri

HostMaster

Effectivement, je ne suis pas encore passé sur ce concept vu qu'il est abordé dans un tutoriel de Tokeur : http://communityscriptproject.com/forum/index.php?topic=160.0

Une classe c'est un élément qui définit les propriétés d'un objet et la manière dont fonctionne l'objet (fonctions/méthodes).
Par exemple, si je veux définir une Renault Mégane, il faut d'abord avoir définir une classe "Voiture" qui va indiquer les propriété marque, modèle, puissance du moteur, nombre de vitesse, matière de la carrosserie etc...
La Renault Mégane sera un objet de la classe Voiture, comme la Peugeot 206 elle a des propriétés du même type mais qui n'ont pas les même valeurs (Renault et Peugeot sont des concessionnaires automobile mais ne sont pas identique pour autant, rien que le nom fait qu'ils sont différent).

Après dans la classe tu peux aussi créer des fonctions qui permet à l'objet de réaliser certaines actions ou d'agir avec d'autres objets. La fonction accélérer devra augmenter la vitesse du véhicule (ce qui modifiera certaines variable de l'objet voiture).
C'est un peu compliqué à expliquer comme ça mais prend en compte le fait que les classes sont les concepts (la voiture, le camion, la moto) et les objets sont ce qui découlent de ces concepts (la renault mégane, la vespa etc...)

Dans RPG Maker nous avons Game_Character qui est la classe qui définir ce qu'est un "Avatar" qu'il soit PNJ ou que ce soit le Joueur (ça peut aussi être un élément de décors mais ça c'est une hérésie d'RPG Maker qui nous est bien pratique).
Game_Character définit des fonctions qui permettent aux objets de se déplacer et d'interagir entre eux. Si tu dis à un objet Game_Character de se déplacer à droite, il va vérifie si il peut avancer à droite en regardant le décors (la map) et si y'a pas un autre PNJ dans le passage. (Sous PSDK le Game_Character fait un truc en plus : dire à celui qui le suit d'avancer.)

Voilà, j'espère que c'est plus clair ^^
ln(yo) = <3
Merci Yuri tu explique bien les choses ^^ !

There was an error while thanking
Thanking...