Polymorphisme
Fait partie de la section Programmation orientée objet du Journey Ruby de Coddy. Leçon 32 sur 57.
Le polymorphisme signifie qu’un même appel de méthode fonctionne sur des objets de classes différentes, et que chaque objet répond à sa manière. Le code qui parcourt des formes appelle area sur chacune d’elles sans demander de quel type de forme il s’agit :
class Shape
def to_s
format("%s %.2f", self.class.name.downcase, area)
end
end
class Circle < Shape
def initialize(r)
@r = r
end
def area
3.14159 * @r * @r
end
end
class Square < Shape
def initialize(side)
@side = side
end
def area
@side * @side
end
end
shapes = [Circle.new(1), Square.new(3)]
shapes.each { |s| puts s }
puts format("total %.2f", shapes.sum(&:area))Sortie :
circle 3.14
square 9.00
total 12.14Sans polymorphisme, l’appelant doit vérifier le type de chaque objet et répéter cette vérification partout où la différence importe. Avec le polymorphisme, la différence réside dans chaque classe :
# sans polymorphisme
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end
# avec polymorphisme
shape.areaAjouter un nouveau type d’objet ne nécessite donc aucune modification du code appelant : une nouvelle sous-classe avec sa propre méthode area fonctionne dans toute boucle déjà existante :
class Shape
def describe
"area #{area}"
end
end
class Square < Shape
def area
4
end
end
class Triangle < Shape
def area
6
end
end
[Square.new, Triangle.new].each { |s| puts s.describe }Sortie :
area 4
area 6to_s est l’exemple courant : puts l’appelle sur n’importe quel objet, et chaque classe y répond différemment. Vos classes participent elles aussi en définissant leur propre to_s :
class Coin
def to_s
"a coin"
end
end
[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }Sortie :
[42]
[text]
[]
[[1, 2]]
[a coin]Défi
FacileComplétez les formes. Shape#to_s renvoie circle: 3.14, le nom de la classe en minuscules et l’aire avec deux décimales, et chaque sous-classe fournit area : Circle.new(r) (utilisez 3.14159 pour pi), Rectangle.new(w, h) et Triangle.new(base, height).
Le code fourni lit les lignes circle 1, rectangle 2 3 ou triangle 4 5, affiche chaque forme, puis total: 22.14 et largest: rectangle: 6.00, en utilisant uniquement to_s et area.
Votre code doit se trouver dans shape.rb, circle.rb, rectangle.rb et triangle.rb. main.rb contient le code d’entrée/sortie fourni et ne peut pas être modifié.
Essayez vous-même
require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'
# Code d'entrée/sortie fourni : le garder tel quel
input = []
while (line = gets)
input << line.chomp
end
kinds = { "circle" => Circle, "rectangle" => Rectangle, "triangle" => Triangle }
shapes = input.map do |line|
kind, *numbers = line.split
kinds[kind].new(*numbers.map(&:to_f))
end
shapes.each { |s| puts s }
puts format("total: %.2f", shapes.sum(&:area))
puts "largest: #{shapes.max_by(&:area)}"
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Classes et objets
Travailler avec des fichiersDéfinir des classesVariables d’instanceMéthodes et selfto_s et inspectRécapitulatif - Carte de bibliothèque4Encapsulation
Méthodes privéesMéthodes protégéesSetters privésProtéger l’étatRécapitulatif - Distributeur automatique7Polymorphisme et typage canard
PolymorphismeTypage canardMéthodes abstraitesCas et classesRécapitulatif - méthodes de paiement10Patrons de conception – Partie 2
Délégation avec ForwardablePatron DécorateurPatron BuilderPatron État2Accesseurs et self
Lecteurs et écrivainsSetters personnalisésself dans les méthodesIdentité et égalitéRécapitulatif - Liste de contacts5Héritage
Sous-classesRedéfinition des méthodesAppeler superis_a? et ancêtresRécapitulatif - Paie du personnel8Méthodes spéciales
Égalité et hachageMéthodes d’opérateursIndexation et ajoutCollections personnaliséesRécapitulatif - Fractions11Projet : Gestion de bibliothèque
Livres et membresEmprunter des livresEntraînez-vous par vous-même : Compilateur Ruby en ligne