2014-02-20 22 views
0

对Ruby的安静新我找不出什么东西。 下面是一个示例代码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') 

目的是有很多子类来大的,我喜欢以避免在每个

def convert(val) 
    return conversion_specific_to_subclass(val) 
end 

定义做前一种方法,我只是为每个一行子类。但不能让它工作。 我在做什么错了?有没有更好的方法来实现我所希望的?

在此先感谢

编辑:问这里是错误的代码产生(红宝石2.1.0)

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

你是什么意思“不起作用”?有错误吗?其他输出?请更具体一些。 – Linuxios

+0

使用amperstamp(b&)我然后有:test2.rb:14:'':未定义的方法'转换器'为Small:Class(NoMethodError)希望它会帮助;) – zedryas

回答

3

你太过于复杂 - 因为你只需要将块绑定到特定的方法名就可以了!

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定义的参数列表中的类方法,并且返回值将是你的块的返回值。

+0

没想到,+1。 – Linuxios

+0

非常感谢 - 确实更简单 – zedryas

+0

OUPS - 没有完全理解 - 调用Small.convert时我们调用生成的函数时怎么办? – zedryas

0

试试这个代码:

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') 

有两个你的代码存在问题。一,你必须使用&参数捕获块。所以,这是新的方法声明:

def self.convertor(&b) 

最后,你有你的回用块调用语法来调用该块,像这样:

return b[val] 

或者这样:

return b.call(val) 

您不能调用类似b val的块。

另外,在Ruby中始终在括号中包含括号是很好的风格。

+0

这已经完成了,非常感谢:) :)。快速的问题是最好是使用块,或在Big#convertor方法中使用yield?最后,我如何关闭这个主题? – zedryas

+0

@dryas:你可以使用yield,但是Chris的解决方案比较干净。另外,通过接受答案,您可以将问题标记为已解决。 – Linuxios