【问题标题】:Ruby trying to programatically avoid multiple definitions in subclassesRuby 试图以编程方式避免子类中的多个定义
【发布时间】:2014-03-22 05:41:59
【问题描述】:

对 ruby​​ 很陌生,我想不通。 这是一个示例代码

class Big
  def self.metaclass; class << self; self; end; end

  def self.convertor b
    metaclass.instance_eval do
      define_method( :convert ) do |val|
        return b val
       end
    end
  end
end

class Small < Big
  convertor { |v| v.to_i + 1 }
end

puts Small.convert('18')

目的是为 Big 提供很多子类,我希望避免在每个子类中定义

def convert(val)
  return conversion_specific_to_subclass(val)
end

按照前一种方式,每个子类只有一行。但不能让它工作。 我做错了什么?有没有更好的方法来实现我的愿望?

提前致谢

编辑:这里问的是这段代码产生的错误(使用 ruby​​ 2.1.0)

test2.rb:4:in `convertor': wrong number of arguments (0 for 1) (ArgumentError)
from test2.rb:14:in `<class:Small>'`

【问题讨论】:

  • “不起作用”是什么意思?有错误吗?其他输出?请更具体。
  • 使用ampstamp (b&) 然后我有:test2.rb:14:in &lt;class:Small&gt;': undefined method convertor' for Small:Class (NoMethodError) 希望它会有所帮助;)

标签: ruby metaclass


【解决方案1】:

试试这个代码:

class Big
  def self.metaclass; class << self; self; end; end

  def self.convertor(&b)
    metaclass.instance_eval do
      define_method( :convert ) do |val|
        return b[val]
       end
    end
  end
end

class Small < Big
  convertor { |v| v.to_i + 1 }
end

puts Small.convert('18')

您的代码中有两个问题。一,您必须使用&amp; 参数来捕获块。所以,这是新的方法声明:

def self.convertor(&b)

最后,您必须在返回时使用块调用语法来调用块,如下所示:

return b[val]

或者这个:

return b.call(val)

你不能调用像b val这样的块。

此外,在 Ruby 中,始终在任何地方都包含括号是一种很好的风格。

【讨论】:

  • 已经完成了,非常感谢:):)。快速的问题是最好按原样使用块还是在 Big#convertor 方法中使用 yield?最后我该如何结束这个主题?
  • @dryas:你可以只使用 yield,但上面 Chris 的解决方案更干净。此外,通过接受答案,您可以将问题标记为已解决。
【解决方案2】:

您过于复杂了 - 因为您想要的只是将块绑定到特定方法名称的能力,那就去做吧!

class Big
  def self.converter(&block)
    define_singleton_method :convert, &block
  end
end

class Small < Big
  converter {|v| v.to_i + 1 }
end

这样,当您调用 Small::converter 时,它将定义一个类方法,该方法接受您的块 args 中定义的参数列表,返回值将是您的块的返回值。

【讨论】:

  • 没想到,+1。
  • OUps - 不完全理解 - 为什么在调用 Small.convert 时我们会调用生成的函数?
  • 糟糕。我的代码将convert 定义为实例方法;我会解决的。
  • 运行它时我得到了:test2.rb:2:in convert': wrong number of arguments (1 for 0) (ArgumentError) from test2.rb:11:in
    '
  • 已更新。这应该更接近你想要的。
猜你喜欢
  • 2012-03-15
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-04
  • 2016-12-04
  • 1970-01-01
相关资源
最近更新 更多