Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何基于类动态定义模块方法';实例变量?_Ruby - Fatal编程技术网

Ruby 如何基于类动态定义模块方法';实例变量?

Ruby 如何基于类动态定义模块方法';实例变量?,ruby,Ruby,我有以下课程: class Foo include BaseFoo attr_reader :with_context def initialize(with_context: %i[bar baz]) @with_context = with_context end def call puts bar # Should return 'lorem ipsum' puts baz # Should return 'lorem ipsum' e

我有以下课程:

class Foo
  include BaseFoo

  attr_reader :with_context

  def initialize(with_context: %i[bar baz])
    @with_context = with_context
  end

  def call
    puts bar # Should return 'lorem ipsum'
    puts baz # Should return 'lorem ipsum'
  end
end
如何在模块
BaseFoo
中根据
的值和上下文动态定义方法

不幸的是,这不起作用,因为模块不知道上下文是什么。 而是让你大致了解需要实现的目标。伪代码:

module BaseFoo
  with_context.each |context|
    define_method context do
      'lorem ipsum'
    end
  end
end
基本上,
BaseFoo
应该具有以下公共方法:

def bar
  'lorem ipsum'
end

def baz
  'lorem ipsum'
end

如果不与模块进行实际交互,就无法真正做到这一点。当一个模块包含在其包含在类中时,该类会将该模块放置在类的祖先链上,并在该模块上触发
module#included
回调

由于这种情况发生在类级别,因此除非您实际调用实例方法,否则无法访问实例的上下文。在这种情况下,
self
是包含模块的类的实例:

module BaseFoo
  def extend_base_foo
    with_context.each do |context|
      BaseFoo.module_eval do
        define_method context do
          'lorem ipsum'
        end
      end
    end
  end
end

class Foo
  include BaseFoo

  attr_reader :with_context

  def initialize(with_context: %i[bar baz])
    @with_context = with_context
    extend_base_foo
  end

  def call
    puts bar # Should return 'lorem ipsum'
    puts baz # Should return 'lorem ipsum'
  end
end
但老实说,你到底为什么要这么做?创建一个Foo实例实际上会在模块本身上定义这些方法,这意味着它们包含在每个Foo实例中:

Foo.new(with_context: [:x, :y])
Foo.new.x # loren ipsum - big WTF moment
如果确实要执行类似操作,请创建一个匿名模块并使用它扩展实例:

class Foo
  def initialize(with_context: %i[bar baz])
    m = Module.new do
      with_context.each do |context|
        define_method(context) do
          'lorem ipsum'
        end
      end
    end
    self.extend(m)
  end

  def call
    puts bar # Should return 'lorem ipsum'
    puts baz # Should return 'lorem ipsum'
  end
end

您的第一个示例不起作用
Foo.new.call
返回扩展\u base\u Foo中的
块:为BaseFoo:Module调用私有方法define\u method(NoMethodError)
我在ruby 2.7.0p0(2019-12-25修订版647ee6f091)中运行了它。它可能与版本有关。可能使用
BaseFoo.module\u eval do。。。结束