Menu
Coddy logo textTech

Étendre les objets

Fait partie de la section Programmation orientée objet du Journey Ruby de Coddy. Leçon 28 sur 57.

extend ajoute les méthodes d’un module à un objet au lieu de les ajouter à toutes les instances. Étendre une classe les ajoute à l’objet classe, de sorte qu’elles deviennent des méthodes de classe :

module Describable
  def describe
    "#{name} has #{instance_methods(false).size} methods"
  end
end

class Dog
  extend Describable

  def bark
    "Woof"
  end

  def sit
    "sits"
  end
end

puts Dog.describe

Sortie :

Dog has 2 methods

Un module utilisé avec extend peut conserver son état dans les variables d’instance de la classe. Chaque classe qui l’étend obtient sa propre copie, en tant que variables d’instance de classe :

module Counted
  def created
    @created ||= 0
  end

  def record
    @created = created + 1
  end
end

class Order
  extend Counted
end

class Invoice
  extend Counted
end

Order.record
Order.record
Invoice.record
puts "#{Order.created} #{Invoice.created}"

Sortie :

2 1

extend fonctionne également sur un seul objet. Seul cet objet acquiert les méthodes les autres instances de sa classe restent inchangées, et is_a? vaut true uniquement pour l'objet étendu :

module Shiny
  def polish
    "#{self} is shining"
  end
end

a = "car"
b = "bike"
a.extend(Shiny)
puts a.polish
puts a.is_a?(Shiny)
puts b.respond_to?(:polish)

Sortie :

car is shining
true
false

Les deux mots-clés placent les méthodes du même module à des endroits différents. include en fait des méthodes d’instance d’une classe, tandis que extend en fait des méthodes de l’objet qui est étendu :

class Order
  include Printable    # order.print_me       (chaque instance)
  extend Counted       # Order.record         (la classe elle-même)
end

item.extend(Shiny)     # item.polish          (seulement cet objet)
challenge icon

Défi

Facile

Complétez le module Registry, que les classes utilisent avec extend. register(name) ajoute un nom à la propre liste de la classe, conservée dans @entries (créée lors de la première utilisation), et renvoie Plugin registered x ; un nom déjà présent renvoie Plugin already has x. entries renvoie la liste et count sa taille. Plugin et Theme étendent toutes deux Registry et conservent des listes distinctes.

Le code fourni lit des lignes plugin name ou theme name, appelle register sur la classe correspondante et affiche la réponse. Enfin, il affiche plugins: a, b (2) et themes: ..., ou none (0) pour une liste vide.

Votre code doit se trouver dans registry.rb, plugin.rb et theme.rb. main.rb contient le code d'entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

require_relative 'registry'
require_relative 'plugin'
require_relative 'theme'

# Code d'entrée/sortie fourni : le garder tel quel
input = []
while (line = gets)
  input << line.chomp
end
input.each do |line|
  kind, name = line.split
  target = kind == "plugin" ? Plugin : Theme
  puts target.register(name)
end
[["plugins", Plugin], ["themes", Theme]].each do |label, klass|
  list = klass.entries.empty? ? "none" : klass.entries.join(", ")
  puts "#{label}: #{list} (#{klass.count})"
end
quiz iconTestez-vous

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

Entraînez-vous par vous-même : Compilateur Ruby en ligne