从ruby内部进行施工质量分配
可能重复:
在ruby中创建惯用对象
有时,在构造上为实例变量分配许多构造的参数是有用的。 除了明显的方法:
def initialize(arg1, arg2, arg3) @arg1, @arg2, @arg3 = arg1, arg2, arg3 end
是否有更简洁的习惯用于实现相同的结果? 像scala中发现的东西,例如:
class FancyGreeter(greeting: String) { def greet() = println(greeting) }
在这种情况下,对象FancyGreeter有一个默认构造函数,为它传递的参数提供赋值。
在Ruby 1.8中,块参数和方法参数具有不同的语义:方法参数具有绑定语义 ,块参数具有赋值语义 。
这意味着当您调用方法时,方法参数将绑定到您传入的值。当您调用块时,值将被赋值给参数。
所以,你可以创建一些非常疯狂的块,这似乎没有做任何事情:
lambda {|@a|}.call(42)
块体是空的,但由于参数赋值语义,实例变量@a
将被赋值42
。 它的工作更加疯狂:
lambda {|foo.bar|}.call(42)
是的, attr_writer
方法也可以。 或者怎么样
foo = {} lambda {|foo[:bar]|}.call(42) p foo # => {:bar => 42}
是的,那些。
由于您可以使用块定义方法,因此您可以这样做:
class FancyGreeter define_method(:initialize) {|@greeting|} def greet; puts @greeting end end
甚至
class FancyGreeter attr_accessor :greeting define_method(:initialize) {|self.greeting|} def greet; puts greeting end end
但是,我不建议这样做有两个原因:
- 没有多少Rubyist知道这一点,对那些必须在你之后维护代码的人表示友好。
- 在Ruby 1.9及更高版本中,块参数语义已经消失,块也使用方法参数语义,因此这不再起作用。
我想你可以做….
def initialize *e @a, @b, @c = e end
我不知道“更好”,但有不同程度的“聪明”:
def initialize args={} args.each do |key, value| instance_variable_set "@#{key}", value end end
但是,当你编程时,“聪明”通常是危险的:-)
编辑:鉴于编辑过的问题,我将添加:
Class PickMe def initialize say="what?" @say = say end end
仅仅因为我不知道你是否知道默认选项。 否则,请考虑自我记录代码的价值。 干净利落的“初始化”方法是无价的。
是Andy Hunt或Dave Thomas提出Ruby应该能够处理这种语法来从构造函数参数初始化成员变量:
def initialize(@a, @b, @c) ... end
马茨不接受他们的建议; 我不记得为什么。