Menu
Coddy logo textTech

Estendere gli oggetti

Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 28 di 57.

extend aggiunge i metodi di un modulo a un oggetto invece che a tutte le istanze. Estendere una classe li aggiunge all'oggetto classe, quindi diventano metodi di 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

Output:

Dog has 2 methods

Un modulo usato con extend può mantenere lo stato nelle variabili di istanza della classe. Ogni classe che lo estende ottiene una propria copia, come variabili di istanza della 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}"

Output:

2 1

extend funziona anche su un singolo oggetto. Solo quell'oggetto acquisisce i metodi; le altre istanze della sua classe rimangono invariate e is_a? è true solo per l'oggetto esteso:

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)

Output:

car is shining
true
false

Le due parole chiave collocano i metodi dello stesso modulo in posti diversi. include li rende metodi di istanza di una classe, extend li rende metodi dell'unico oggetto che viene esteso:

class Order
  include Printable    # order.print_me       (ogni istanza)
  extend Counted       # Order.record         (la classe stessa)
end

item.extend(Shiny)     # item.polish          (solo questo oggetto)
challenge icon

Sfida

Facile

Completa il modulo Registry, che le classi usano con extend. register(name) aggiunge un nome all’elenco della classe, conservato in @entries (creato al primo utilizzo), e restituisce Plugin registered x; se il nome è già presente, restituisce Plugin already has x. entries restituisce l’elenco e count la sua dimensione. Sia Plugin che Theme estendono Registry e mantengono elenchi separati.

Il codice fornito legge righe plugin name o theme name, chiama register sulla classe corrispondente e stampa la risposta. Infine stampa plugins: a, b (2) e themes: ..., oppure none (0) se l’elenco è vuoto.

Il tuo codice va inserito in registry.rb, plugin.rb e theme.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

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

# Supplied input/output code: keep it as it is
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Ruby online