【问题标题】:Why isn't this simple test class's method inherited in Ruby?为什么这个简单的测试类的方法不能在 Ruby 中继承?
【发布时间】:2010-05-29 13:31:33
【问题描述】:

考虑这个非常简单的日志类:

class MockLog
  # ...
end

让我们为所有类添加日志记录:

class Module
  def has_logging()
    class_eval {
      @log = MockLog.new
      def log
        self.class.instance_variable_get :@log
      end
    }
  end
end

现在,为什么这不起作用?

class Foo
  has_logging
end
Foo.new.log.nil?   # => false, as expected

class Bar < Foo
end
Bar.new.log.nil?   # => true?! Why wasn't the `log` method inherited?

【问题讨论】:

    标签: ruby class methods


    【解决方案1】:

    日志方法是继承的(如果不是,你会得到一个 NoMethodError),但你的类级实例变量不是,所以instance_variable_get 返回 nil。您应该声明一个常规类变量,例如:

    class Module
      def has_logging()
        class_eval {
          @@log = MockLog.new
          def log
            @@log
          end
        }
      end
    end
    
    class Foo
      has_logging
    end
    
    class Bar < Foo
    end
    

    现在它将被继承。见Class and Instance Variables In Ruby

    【讨论】:

    • Hmm.. 但是如果log 方法被继承了,那么为什么当我们询问它是否为nil 时它返回true?
    • 我认为这不是一个好主意。现在如果你想有一个不同的登录Bar,它不能覆盖Foo中的@@log;他们将全部共享同一个@@log 实例。我认为他想要的行为是“Foo 的子类将使用@@log,除非被覆盖,但如果他们自己调用has_logging,那么该子类将拥有自己的@@log”。
    • 也就是说,假设你有class Quux &lt; Foo; has_logging; end。我认为 OP 希望 Quux.new.log != Foo.new.log 是真的。
    • 继续传奇:Ruby 的类变量是敌是友? (请参阅此处进行一些讨论:oreilly.com/ruby/excerpts/ruby-best-practices/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2015-02-03
    • 2016-05-29
    相关资源
    最近更新 更多