Menu
Coddy logo textTech

Objekte erweitern

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

extend fügt die Methoden eines Moduls einem Objekt hinzu, anstatt sie allen Instanzen hinzuzufügen. Das Erweitern einer Klasse fügt sie dem Klassenobjekt hinzu, sodass sie zu Klassenmethoden werden:

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 seinen Zustand in Instanzvariablen der Klasse speichern. Jede Klasse, die es erweitert, erhält eine eigene Kopie, und zwar 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 bei 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 (bei der ersten Verwendung erstellt), und gibt Plugin registered x zurück; ein Name, der bereits vorhanden ist, gibt Plugin already has x zurück. entries gibt die Liste und count deren Größe zurück. Sowohl Plugin als auch Theme erweitern Registry und verwalten 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. Anschließend 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 Eingabe-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

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

# Gelieferter Ein-/Ausgabe-Code: belasse ihn wie er ist
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