Objectifs
- Comprendre le rôle des méthodes conventionnelles que Ruby appelle implicitement pour vous.
- Personnaliser la représentation textuelle d’un objet pour l’affichage avec
to_s. - Personnaliser la représentation de débogage d’un objet avec
inspect. - Découvrir comment les opérateurs (
+,==,[]) sont aussi des méthodes que l’on peut redéfinir.
En Ruby, il existe une série de méthodes que vous n’appelez pas toujours directement, mais que l’interpréteur utilise “sous le capot” dans certaines situations. En définissant ces méthodes sur vos propres classes, vous donnez à vos objets des super-pouvoirs et vous les intégrez de manière transparente au reste du langage.
to_s : La représentation pour les humains
La méthode to_s (to string) doit retourner une représentation textuelle et lisible de votre objet, destinée à l’affichage final. C’est cette méthode qui est appelée lorsque vous :
- Utilisez
putssur votre objet. - L’insérez dans une chaîne avec l’interpolation (
"mon objet : #{mon_objet}").
class Livre
attr_reader :titre, :auteur
def initialize(titre, auteur)
@titre = titre
@auteur = auteur
end
# On redéfinit to_s
def to_s
"'#{@titre}' par #{@auteur}"
end
end
mon_livre = Livre.new("Le Guide du voyageur galactique", "Douglas Adams")
puts mon_livre # Appelle mon_livre.to_s automatiquement
# => 'Le Guide du voyageur galactique' par Douglas Adams
inspect : La représentation pour les développeurs
La méthode inspect doit retourner une chaîne de caractères qui représente l’objet de manière détaillée et non ambiguë, destinée au débogage. C’est cette méthode qui est appelée par :
p mon_objet(qui est un raccourci pourputs mon_objet.inspect).- La console
irbpour afficher le résultat d’une expression.
class Livre
# ... (initialize et to_s) ...
# On redéfinit inspect
def inspect
"#<Livre titre=\"#{@titre}\" auteur=\"#{@auteur}">"
end
end
mon_livre = Livre.new("Le Guide...", "Douglas Adams")
p mon_livre # Appelle mon_livre.inspect
# => #<Livre titre="Le Guide..." auteur="Douglas Adams">
# C'est beaucoup plus informatif pour un développeur.
Les opérateurs sont des méthodes
En Ruby, la plupart des opérateurs sont en réalité des “sucres syntaxiques” pour des appels de méthode.
| Syntaxe | Équivalent en méthode |
|---|---|
a + b | a.+(b) |
a == b | a.==(b) |
mon_tableau[0] | mon_tableau.[](0) |
mon_tableau[0] = "val" | mon_tableau.[]=(0, "val") |
Cela signifie que vous pouvez redéfinir ces opérateurs dans vos propres classes pour leur donner un comportement spécifique.
class Panier
def initialize
@pommes = 0
end
def add(nombre)
@pommes += nombre
end
# On redéfinit l'opérateur +
def +(autre_panier)
# ... logique pour fusionner deux paniers
end
end
Bonnes pratiques
- Définissez toujours une méthode
to_ssur vos classes pour leur donner une représentation textuelle propre. - Définissez toujours une méthode
inspectpour faciliter grandement le débogage de vos objets dansirbou avecp. - La surcharge d’opérateurs est puissante mais doit être utilisée avec parcimonie et de manière intuitive. Redéfinir
+pour faire une soustraction serait une très mauvaise idée !
Exercices
-
Représentation d’un utilisateur :
- Créez une classe
Utilisateuravec unnomet unemail. - Définissez la méthode
to_spour qu’elle retourne uniquement le nom. - Définissez la méthode
inspectpour qu’elle retourne une chaîne détaillée comme#<Utilisateur nom="Alice" email="alice@exemple.com">. - Dans
irb, créez une instance et testez l’affichage avecputsetp.
- Créez une classe
-
Égalité personnalisée :
- Dans votre classe
Utilisateur, redéfinissez l’opérateur==. - La méthode doit considérer deux utilisateurs comme égaux si leur
emailest identique, même si leur nom est différent.def ==(autre_utilisateur) self.email == autre_utilisateur.email end - Testez en créant deux objets
Utilisateuravec le même email et en les comparant avec==.
- Dans votre classe
-
Accès façon tableau :
- Créez une classe
Configqui stocke un hash de configuration dans une variable d’instance@data. - Définissez la méthode
[]pour qu’elle permette d’accéder directement au hash interne.def [](cle) @data[cle] end - Créez une instance et vérifiez que vous pouvez faire
config[:host]au lieu deconfig.data[:host].
- Créez une classe