【问题标题】:Lazy object in ruby红宝石中的懒惰对象
【发布时间】:2015-08-06 19:30:15
【问题描述】:

如何创建一个本身完全惰性的 opbjet?我有一个块,我想(作为依赖)传递块的“当前值”(在调用时)而不是依赖注入时的值。

我实际上不能传递 lambda,因为所有服务都需要一个实际的对象,所以它们不会向它们发送 :call,只是访问它们。

这个(过于简单化的)例子可以说明情况:

class Timer
  def initialize(current_time)
    @current_time = current_time
  end

  def print_current_time
    print @current_time
  end
end

class Injector
  def current_time
    # a lazy object that when accessed actually calls the lambda below
    # every single time.
  end

  def current_time_lazy
    -> { Time.now }
  end

  def instantiate(class_name)
    # search for the class, look at the constructor and
    # create an instance with the dependencies injected by
    # name
    # but to be simple
    if class_name == "Timer"
      Timer.new(current_time)
    end
  end
end

timer = Injector.new.instantiate("Timer")
timer.print_current_time # => some time
sleep 2
timer.print_current_time # => some *different* time

实际情况意味着传递current_user,但取决于当前用户在注入这些值后可能会更改的情况。

我非常感谢任何建议(即使现在我会仔细排序依赖注入代码,以免发生这种情况,但我认为它非常脆弱)

【问题讨论】:

  • 我不明白你第二段中的“实际对象”,考虑到 lambdas 是对象。
  • @CarySwoveland 当然 lambda 是对象。我需要的是能够传递类似于承诺的东西。因此,获得该承诺/lambda/whatever 的服务将无法区分,但我不需要在注入时手头有对象。

标签: ruby lazy-evaluation


【解决方案1】:

这应该会有所帮助:

class Timer
  def initialize(current_time)
    @current_time = current_time
  end
  def print_current_time
    puts @current_time
  end
end

class LazyMaker < BasicObject
  def self.instantiate(class_name, lambada)
    if class_name == 'Timer'
      ::Timer.new(new(class_name, lambada))
    end
  end
  def initialize(class_name, lambada)
    @lambada = lambada
  end
  def method_missing(method, *args)
    @lambada.call.send(method, *args)
  end
end

timer = LazyMaker.instantiate('Timer', -> { Time.now })
timer.print_current_time # some time
sleep 2
timer.print_current_time # some other time

我正在尝试使用委托来实现它,这样我就可以先调用该块,获取一个新对象并将方法调用重定向到它。为什么这样?因为基本上,访问一个对象来做某事意味着调用它的方法。例如,在print @current_time 中,它发送@current_time.to_s

但由于几乎所有对象都会有一些从 Ruby 中的标准基类继承的方法,如 ObjectLazyMaker 也有像 to_s 这样的方法。所以我想只让LazyMaker 继承自BasicObject,这是一个空白类。所以几乎所有的方法都被委托了。

但是,是的,可能还有其他方法可以做到这一点。

【讨论】:

  • 不错的答案,就像一个超级懒惰的 SimpleDelegator!我试试看:)
猜你喜欢
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多