Les Classes

Résumé Support

Tout au long des chapitres précédent nous avons utiliser des objets comme des entiers, des tableaux ou des chaines de caractères. Lorsque notre application va grandir nous allons vouloir représenter des concepts plus élaborés que ceux proposés par Ruby. On pourra alors utiliser des classes pour définir ces nouveaux objets.

Les instances

class Eleve end jean = Eleve.new marc = Eleve.new

Pour le moment notre class ne fait rien mais il est important de faire un points sur la terminologie. Dans l'exemple précédent jean et marc sont des instances de la classe Eleve. Cela veut dire qu'ils sont construit sur le même modèle mais qu'ils ne sont pas réellement identique. Si on rapproche ça avec ce que nous avont déjà vu les chiffre 1 et 2 sont des instances de la class Fixnum.

Les classes que l'on définit peuvent contenir des méthodes

class Eleve def marcher puts "Je marche" end end jean = Eleve.new jean.marcher

Il est possible de définir une méthode spéciale initialize, cette méthode est automatiquement appellée à la construction d'une nouvelle instance, lors de l'utilisation de new, il est aussi possible de lui assigner des arguments.

class Eleve def initialize(nom) @nom = nom end end jean = Eleve.new("Jean")

Dans l'exemple précédent, on remarque qu'une varialbe possède un @ devant son nom. Ce @ permet de désigner une variable d'instance. Cela veut dire que chaque instance de la classe Eleve aura une copie unique de la variable @nom

class Eleve def initialize(nom) @nom = nom end def direNom puts "Je suis #{@nom}" end end Eleve.new("Jean").direNom # Je suis Jean Eleve.new("Marc").direNom # Je suis Marc

Ici la valeur de @nom dépend de l'instance. Jean et Marc possède chacun une valeur différente pour cette variable.
Il est possible de rendre une variable d'instance facilement accessible depuis une instance en utilisant un système d'accesseurs / mutateurs (getters/setters en anglais)

class Eleve def taille @taille end def taille=(valeur) @taille = valeur end end jean = Eleve.new # On peut maintenant modifier / récupérer taille facilement jean.taille = 150 puts jean.taille # 150

Il existe un racourci pour définir ces accesseurs / mutateur pour gagner du temps et éviter de devoir déclarer des tonnes de méthodes si nous avons beaucoup de variables d'instances à rendre accessible.

class Eleve attr_accessor :taille, :age, :nom end

Il existe plusieurs variantes :

  • attr_accessor, crée un getter et un setter pour chaque variable
  • attr_reader, crée un getter pour chaque variable
  • attr_writer, crée un setter pour chaque variable

Public / Privée

Dans des classes complexes nous allons parfois séparer certaines de nos méthodes afin de garder un code propre et simple. Certaines méthode n'auront pas lieu de se retrouver disponible sur les instances. On pourra alors créer des méthodes privées

class Eleve attr_accessor :notes def moyenne sommeNotes / @notes.length end private def sommeNotes @notes.inject(:+) end end jean = Eleve.new jean.notes = [10, 16] puts jean.moyenne # 13

Dans ce cas-là, la méthode permettant de faire la somme des notes n'a pas d'interêt à être accessible depuis l'instance, on la rend donc privée. Si on essaie de l'appeller depuis l'instance on obtiendra une erreur.

jean.sommeNotes # NoMethodError: private method `sommeNotes' called

Rendre des méthodes privées n'apportent rien en terme fonctionnel mais permet de rendre la lecture d'une classe plus facile. Car on saura en un clin d'oeil les méthodes que l'on peut uiliser sur les instances. Cela permet de garder un code propre et une API simple.

Les méthodes de classes

Les classes en elle même peuvent aussi contenir des méthodes, ces méthodes sont appellées méthode de classes

class Eleve def self.moyenne 10 end end puts Eleve.moyenne # 10

Contrairement aux méthodes d'instance vues précédemment, ces méthodes sont appellées directement sur la classe (il n'est donc pas nécessaire de créer une instance pour les appeller). De la même manière il existe aussi des variables de classe. Ces variables sont symbolisées par `@@``

class Eleve @@moyenne = 10 def self.afficherMoyenne puts @@moyenne end # une méthode de classe peut être appellé depuis la classe # Là c'est inutle mais il faut savoir que l'on peut le faire afficherMoyenne # 10 end Eleve.showMoyenne # 10

Cela nous permet maintenant d'élucider le mystère de attr_accessor vu précédemment. attr_accessor est en fait une méthode de classe qui, lorsqu'elle est appellée, a pour effet de créer les accesseur et mutateurs. C'est ce qu'on appelle du MétaProgramming, le code est capable de se modifier lui même.