Es gibt ein paar Unterschiede, die helfen können, einen Einblick zu geben, welcher Ansatz zu verwenden ist.
1) Sie können sicher Primitiven delegieren (zB String), kann aber nicht immer sicher von ihnen erben
Wenn Sie oben auf Hash
oder String
oder Fixnum
bauen, sind Sie sicherer DelegateClass
mit (oder ein anderer Delegierer). Für mehr auf warum, Steve Klabnik's cautioning ist ein guter Ort, um zu beginnen).
2) DelegateClass macht es einfach, ein allgemeineres Ziel in eine spezifischere zu „konvertieren“ ein
Dies macht es einfacher, eine Instanz eines allgemeine Aufgabe zu übernehmen und sie in einer Weise verhalten, die spezifisch ist zu Ihrer Implementierung:
class Message < DelegateClass(String)
def print
upcase
end
end
# […]
def log(message)
message = Message.new(message) unless message.is_a?(Message)
end
3) gotcha: DelegateClass
Subklassen erwarten eine Instanz der delegierte Klasse als Argument an new
Dies kann die "Unterklasse" von Klassen, die Sie an den Bibliothekscode übergeben, erschweren. Zum Beispiel ist dies eine ziemlich gängige Praxis, die mit DelegateClass
aus der Box wird nicht funktionieren:
class MyLogger < DelegateClass(ActiveSupport::Logger); end
Foo::ThirdParty::Library.configure do |c|
c.logger = MyLogger # no good
end
Das funktioniert nicht, weil unsere Bibliothek wie die meisten Logger verhalten erwartet und ohne Argumente instanziiert. Dies kann behoben werden, indem initialize
definiert und eine Instanz von ActiveSupport::Logger
erstellt wird, aber in diesem Fall wahrscheinlich nicht die richtige Lösung.