从红宝石内部施工的质量分配 [英] Mass assignment on construction from within 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中,块参数和方法参数有不同的语义:方法参数
这意味着当你调用一个方法时,方法参数get 绑定到你传递的值。当你调用一个块,值分配到参数。
lambda {
| @a |} .call(42)
块体是空的,赋值语义,实例变量 @a
将被赋值 42
。它工作甚至更疯狂:
lambda {| foo.bar |} .call(42)
是, attr_writer
方法也可以。或者
foo = {}
lambda {| foo [:bar] |} .call
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; put greeting end
end
但是,我不推荐这个有两个原因: / p>
- 没有多少Rubyists知道这一点,对那些在你之后必须维护代码的人来说很好。
- 在Ruby 1.9及更高版本中,块参数语义已经消失,块也使用方法参数语义,因此这不再工作。
Possible Duplicate:
Idiomatic object creation in ruby
Sometimes it's useful to assign numerous of a constructed arguments to instance variables on construction. Other than the obvious method:
def initialize(arg1, arg2, arg3)
@arg1, @arg2, @arg3 = arg1, arg2, arg3
end
Is there a more concise idiom for achieving the same result? Something like that found in scala for instance:
class FancyGreeter(greeting: String) {
def greet() = println(greeting)
}
Where in this case the object FancyGreeter has a default constructor that provides assignment for it's passed arguments.
In Ruby 1.8, block arguments and method arguments have different semantics: method arguments have binding semantics, block arguments have assignment semantics.
What that means is that when you call a method, the method arguments get bound to the values that you pass in. When you call a block, the values get assigned to the arguments.
So, you can create some pretty crazy looking blocks that way, that seemingly don't do anything:
lambda {|@a|}.call(42)
The block body is empty, but because of the argument assignment semantics, the instance variable @a
will be assigned the value 42
. It works even crazier:
lambda {|foo.bar|}.call(42)
Yes, attr_writer
methods work too. Or what about
foo = {}
lambda {|foo[:bar]|}.call(42)
p foo # => {:bar => 42}
Yup, those too.
And since you can define methods using blocks, you can do this:
class FancyGreeter
define_method(:initialize) {|@greeting|}
def greet; puts @greeting end
end
or even
class FancyGreeter
attr_accessor :greeting
define_method(:initialize) {|self.greeting|}
def greet; puts greeting end
end
However, I wouldn't recommend this for two reasons:
- Not many Rubyists know this, be kind to the people who have to maintain the code after you.
- In Ruby 1.9 and onwards, block argument semantics are gone, blocks also use method argument semantics, therefore this does no longer work.
这篇关于从红宝石内部施工的质量分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!