DelegateClass vs Class Inheritance in Ruby

DelegateClass vs Class Inheritance in Ruby

有人可以提供一些关于何时通过 DelegateClass(例如 Seller < DelegateClass(Person))使用委托以及何时使用 class 继承(例如 Seller < Person)的见解吗? ruby?

class Seller < DelegateClass(Person)
  def sales
     ...
  end 
end 

class Seller < Person 
  def sales
     ...
  end 
end 

当我查看 Rails 上 Github 上的 Ruby 来源时,我发现了很多 uses of DelegateClass.

代表根据上下文为 Person 的不同行为建模。例如同一个人在一种情况下可能是卖方,在另一种情况下可能是买方。继承更加严格:BearTiger 继承自 Animal,但是 Animal 的实例永远不需要有时表现得像 Bear,有时表现得像像 TigerAnimal 的后代实例是其中之一。

有一些差异可以帮助深入了解使用哪种方法。

1) 您可以安全地委托给基元(例如 String),但不能总是安全地从它们继承

如果您在 HashStringFixnum 之上构建,您使用 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 subclasses 期望委托 class 的实例作为 new[=41 的参数=]

这可能会使“subclass”变得棘手 class您要交给图书馆代码。例如,这是一种相当普遍的做法,无法立即使用 DelegateClass:

class MyLogger < DelegateClass(ActiveSupport::Logger); end

Foo::ThirdParty::Library.configure do |c|
  c.logger = MyLogger # no good
end

这行不通,因为我们的库希望像大多数记录器一样运行并且不带参数进行实例化。这可以通过定义 initialize 并创建 ActiveSupport::Logger 的实例来解决,但在这种情况下可能不是正确的解决方案。