你可以做这样的事情:
class Klass
def initialize(number)
@number = number
end
def result
@number
end
def method_missing(method_name, *arguments, &block)
if @number.respond_to?(method_name)
@number = @number.method(method_name).call(*arguments, &block)
return self
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
# be sure to implement this...
end
end
puts Klass.new(5).pred.pred.result # => 3
但它是有问题的。在这个特殊的例子中,由于#pred返回一个新的对象(它不会修改它被调用的对象),我们必须重新分配实例变量给结果。它适用于返回新整数的pred和其他方法,但Integer上的某些方法不返回整数(例如Integer#even)。在这种情况下,你会得到这样的行为:
puts Klass.new(4).even?.result # => true
根据你的具体情况,这可能是你在追求什么。或者,在您的情况下,可能会被委派的对象的所有方法改变该对象,而不是返回该对象的新实例,在这种情况下,不需要重新分配。
我不认为你可以使用Ruby的现有Delegator和SimpleDelegator结构,因为你可以将最终的#result调用链接到最后的唯一方式是每个委托调用返回Klass的实例。使用这些现有的构造会导致委托调用返回它们的正常返回值,然后链接将返回那些返回值返回的对象。例如,使用上面的代码,你会看到这种现象:
puts Klass.new(5).pred.pred.class # => "Klass"
使用SimpleDelegator,你会看到此行为
require 'delegate'
class Klass2 < SimpleDelegator
# Klass2 methods...
end
puts Klass2.new(5).pred.pred.class # => "Fixnum"
希望有所帮助。
'Klass.new(5).pred.pred.result'严重违反了[Demeter法](https://en.wikipedia.org/wiki/Law_of_Demeter)。你应该重新考虑你的设计。也许只有一个方法调用'self.get_result_for_second_pred_of(number)'并完成'Klass'中的所有工作? – spickermann 2015-02-23 21:00:14
这不是我的设计,我不能遗憾。我必须与此合作。 – mariya 2015-02-23 21:04:20