Ruby中的懒惰评估

我有Ruby的情况,可能需要创建一个对象,但它不确定。 由于对象的创建可能代价高昂,因此我并不急于创建它。 我认为这是延迟加载的明显案例。 如何定义仅在有人向其发送消息时才创建的对象? 该对象将在块中创建。 有没有办法在Ruby中进行简单的延迟加载/初始化? 这些东西是否支持这些东西,它们为各种懒惰的对象初始化提供了不同的解决方案? 谢谢你的建议!

有两种方法。

第一种是让调用者处理惰性对象创建。 这是最简单的解决方案,它是Ruby代码中非常常见的模式

class ExpensiveObject def initialize # Expensive stuff here. end end class Caller def some_method my_object.do_something end def my_object # Expensive object is created when my_object is called. Subsequent calls # will return the same object. @my_object ||= ExpensiveObject.new end end 

第二个选项是让对象懒洋洋地初始化。 我们围绕实际对象创建一个委托对象来实现这一目标。 这种方法有点棘手,不推荐使用,除非您有现有的无法修改的调用代码,例如。

 class ExpensiveObject # Delegate class RealExpensiveObject # Actual object def initialize # Expensive stuff here. end # More methods... end def initialize(*args) @init_args = args end def method_missing(method, *args) # Delegate to expensive object. __object method will create the expensive # object if necessary. __object__.send(method, *args) end def __object__ @object ||= RealExpensiveObject.new(*@init_args) end end # This will only create the wrapper object (cheap). obj = ExpensiveObject.new # Only when the first message is sent will the internal object be initialised. obj.do_something 

您还可以使用stdlib delegate来构建它。

如果您想懒惰地评估代码片段,请使用代理:

 class LazyProxy # blank slate... (use BasicObject in Ruby 1.9) instance_methods.each do |method| undef_method(method) unless method =~ /^__/ end def initialize(&lazy_proxy_block) @lazy_proxy_block = lazy_proxy_block end def method_missing(method, *args, &block) @lazy_proxy_obj ||= @lazy_proxy_block.call # evaluate the real receiver @lazy_proxy_obj.send(method, *args, &block) # delegate unknown methods to the real receiver end end 

然后你像这样使用它:

 expensive_object = LazyProxy.new { ExpensiveObject.new } expensive_object.do_something 

您可以使用此代码对昂贵的东西进行任意复杂的初始化:

 expensive_object = LazyProxy.new do expensive_helper = ExpensiveHelper.new do_really_expensive_stuff_with(expensive_helper) ExpensiveObject.new(:using => expensive_helper) end expensive_object.do_something 

它是如何工作的? 您实例化一个LazyProxy对象,该对象包含有关如何在Proc中构建一些昂贵对象的说明。 如果然后在代理对象上调用某个方法,它首先实例化昂贵的对象,然后将方法调用委托给它。