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.