【问题标题】:Calling original new() method from within overridden new()?从覆盖的 new() 中调用原始 new() 方法?
【发布时间】:2013-04-17 20:58:38
【问题描述】:

我有一个类,它的initialize 方法从远程源获取数据,然后用它来设置它的对象属性。

我预计这个类会被大量使用,在一个程序中可能会被使用数百次。我想通过缓存已经实例化的对象来减少网络调用的开销,然后当他们要求再次实例化该对象时我会返回给用户。

为此,我一直在考虑重写这个类的新方法。它将检查缓存的对象是否可用,如果可用,则返回该引用。否则,它将调用对象的常规 new 方法,该方法将分配内存并像往常一样调用 initialize

如果我在类中重写new() 方法,是否可以通过super() 之类的方式调用原始new 方法?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    是的,不带参数的super 将调用父方法,并将相同的参数传递给新方法。

    或者,您可以通过将参数添加到 super(p1, p2, ...) 来挑选参数。

    关于你想通过记住以前的调用来做什么,称为"memoizing",并且至少有一个memoize gem,或者,您可以根据需要编写自己的。

    使用哈希很容易做到。使用调用new方法时使用的参数作为key,value是你要返回的实例。如果没有您的代码示例,很难想出一个适合您的示例,但这是一个简单的、未经测试的版本:

    def initialize(*args)
      @memoizer ||= {}
      return @memoizer[args] if @memoizer[args]
      # do what you will with the args in this initializer, 
      # then create a new instance for the future.
      @memoizer[args] = super(args)
    end
    

    这个想法是@memoizer 记住调用的“arity”并自动返回类似调用的结果。如果在计算并创建新实例然后返回它之前没有看到那组参数。

    当结果可能会随着相同的输入参数集而改变时,这会发生故障。您不想记忆数据库调用或使用random 或日期/时间值的任何内容,或者返回您无法控制的内容。在这些情况下尝试使用它会返回陈旧或错误的值,除非您设计一种方法来定期扫描并重新验证 @memoizer 值。

    此外,没有刷新机制,因此@memoizer 只会增加大小,并且可能会在给定足够不同的输入值的情况下消耗所有可用空间。为了解决这个问题,您还可以设置将值添加到@memoizer 的时间戳,并定期清除超过给定生命周期的条目。只有“实时”值会保留在哈希中。

    有用的信息在:“Memoize Techniques in Ruby and Rails”。

    【讨论】:

    • 感谢您的帮助!这是我的覆盖代码,这会破坏什么吗? def self.new(*args) # Check whether to return a memoized object # If no object exists, then instantiate a new object super(*args) end
    【解决方案2】:

    通过superalias_method

    如果你是子类,super 会更好

    检查这个:When monkey patching a method, can you call the overridden method from the new implementation?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 2020-12-25
      • 2021-04-30
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      相关资源
      最近更新 更多