Menu
CoddyTech

Objekte erweitern

Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 28 von 57.

extend fügt die Methoden eines Moduls einem einzelnen Objekt hinzu, anstatt allen Instanzen. Wenn du eine Klasse erweiterst, werden sie dem Klassenobjekt hinzugefügt und werden so zu Klassenmethoden:

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

Ausgabe:

Dog has 2 methods

Ein mit extend verwendetes Modul kann den Zustand in Instanzvariablen der Klasse speichern. Jede Klasse, die es erweitert, erhält eine eigene Kopie, als Klasseninstanzvariablen:

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}"

Ausgabe:

2 1

extend funktioniert auch mit einem einzelnen Objekt. Nur dieses Objekt erhält die Methoden; andere Instanzen seiner Klasse bleiben unverändert, und is_a? ist nur für das erweiterte Objekt true:

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)

Ausgabe:

car is shining
true
false

Die beiden Schlüsselwörter platzieren die Methoden desselben Moduls an unterschiedlichen Stellen. include macht sie zu Instanzmethoden einer Klasse, extend macht sie zu Methoden des einen Objekts, das erweitert wird:

class Order
  include Printable    # order.print_me       (jede Instanz)
  extend Counted       # Order.record         (die Klasse selbst)
end

item.extend(Shiny)     # item.polish          (nur dieses Objekt)
challenge icon

Aufgabe

Einfach

Vervollständige das Modul Registry, das Klassen mit extend verwenden. register(name) fügt einen Namen zur eigenen Liste der Klasse hinzu, die in @entries gespeichert wird (und bei der ersten Verwendung erstellt wird), und gibt Plugin registered x zurück; ist ein Name bereits vorhanden, wird Plugin already has x zurückgegeben. entries gibt die Liste zurück und count ihre Größe. Sowohl Plugin als auch Theme erweitern Registry und führen getrennte Listen.

Der bereitgestellte Code liest Zeilen im Format plugin name oder theme name, ruft register für die passende Klasse auf und gibt die Antwort aus. Schließlich gibt er plugins: a, b (2) und themes: ... aus, oder bei einer leeren Liste none (0).

Dein Code gehört in registry.rb, plugin.rb und theme.rb. main.rb enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

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

# Vorgegebener Eingabe-/Ausgabecode: unverändert lassen
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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Ruby-Compiler