Есть несколько отличий, которые могут помочь обеспечить понимание того, какой подход использовать.
1) Вы можете безопасно делегировать примитивов (например, строка), но не всегда безопасно наследовать от них
Если вы строите на вершине Hash
или String
или Fixnum
, вы безопаснее с помощью DelegateClass
(или другим делегатом). Для получения дополнительной информации о том, почему, Steve Klabnik's cautioning - это хорошее место для начала).
2) DelegateClass позволяет легко «конвертировать» более общий объект в более конкретный один
Это делает его легче принять экземпляр общего объекта и заставить его вести себя таким образом, что это конкретные для своей реализации:
class Message < DelegateClass(String)
def print
upcase
end
end
# […]
def log(message)
message = Message.new(message) unless message.is_a?(Message)
end
3) А Гоча: DelegateClass
подклассов ожидать экземпляр делегированного класса в качестве аргумента в new
Это может сделать его сложным для классов «подкласса», которые вы передаете библиотечному коду. Например, это довольно распространенная практика, которая не будет работать из коробки с DelegateClass
:
class MyLogger < DelegateClass(ActiveSupport::Logger); end
Foo::ThirdParty::Library.configure do |c|
c.logger = MyLogger # no good
end
Это не работает, потому что наша библиотека планирует вести себя, как и большинство регистраторов и экземпляр без аргументов. Это можно решить, установив initialize
и создав экземпляр ActiveSupport::Logger
, но, вероятно, это не правильное решение.