ruby 调用instance_methods方法时遇到意外结果,导致返回空数组

sqougxex  于 2023-02-12  发布在  Ruby
关注(0)|答案(1)|浏览(104)

请考虑下面的代码

class Execute
  def self.inherited(klass)
    puts "Class Inherited: #{klass}"
    klass.run
  end

  def self.run
    puts "Running Instance Methods"
    instance_methods(false).each do |m|
      if m.to_s.start_with?("test_")
        puts "Executing Method: #{m}"
        new.send(m)
      end
    end
  end
end

puts "Before class definition"

class Raja < Execute
  def test_1
    puts 'test_1'
  end

  def test_2
    puts 'test_2'
  end

  def test_3
    puts 'test_3'
  end
end

puts "After class definition"

我现在正在尝试通过示例化父类中的一个对象来访问test_1、test_2和test_3方法。在检查程序时,您可能会理解我正在执行的操作。然而,问题出现了,因为调用instance_methods方法返回了一个空数组,与其提供示例方法名称的预期行为相反,即test_1、test_2和test_3。我不知道为什么会出现这种差异,并将非常感谢任何帮助解决此问题

t3irkdon

t3irkdon1#

Class#inherited在继承时被调用,此时还没有定义instance_methods(自使用false以来的非继承示例方法)。

class Raja < Execute #inherited is called here 
 # methods are defined here
end

它将与以下内容类似

class Raja;end 
Raja.instance_methods(false) #=> []
class Raja
  def test_1 = 'test1'
end

你可以看看Module#method_added,但是我不清楚这段代码背后的原因,所以我所能做的就是回答“为什么”你正在经历你正在经历的事情。

更新基于OP注解,寻找类似于test-unit的自动运行机制:

作为一个非常简单的示例:

class Tracker
  @@runner = {} 
  def self.runner
    @@runner
  end 
  def self.inherited(klass) 
    runner[klass] = [] 
  end 
  def self.method_added(method_name)
    runner[self] << method_name if method_name.match?(/test_/)
  end 
end 

class Runner 
 def self.run
    Tracker.runner.each do |klass,tests|
      tests.each do |m| 
        klass.new.send(m)
      end 
    end 
  end
end 
# Run the Runner before the program exits
at_exit { Runner.run}

然后(foo.rb)

require 'runner_tracker'
class Foo < Tracker 
  def test_1
    puts 'test_1'
  end

  def test_2
    puts 'test_2'
  end

  def test_3
    puts 'test_3'
  end
end

产出

> ruby foo.rb
test_1
test_2
test_3

相关问题