有人可以通过DelegateClass
(例如Seller < DelegateClass(Person)
)以及何时在ruby中使用类继承(例如Seller < Person
)来提供有关何时使用委派的一些见解?
class Seller < DelegateClass(Person)
def sales
...
end
end
class Seller < Person
def sales
...
end
end
当我在Github上查看Ruby on Rails源代码时,我发现了很多uses of DelegateClass
。
答案 0 :(得分:7)
有一些差异有助于深入了解使用哪种方法。
1)您可以安全地委托给基元(例如String),但不能总是安全地从它们继承
如果您在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
的实例来解决,但在这种情况下可能不是正确的解决方案。
答案 1 :(得分:2)
委托根据上下文对Person
的不同行为进行建模。例如同一个人可以是一个上下文中的卖方,也可以是不同上下文中的买方。继承更加严格:Bear
和Tiger
继承自Animal
,但Animal
的实例永远不需要有时像Bear
那样行事,有时也会表现出来像Tiger
。 Animal
的后代的实例是一个或另一个。