从红宝石内部施工的质量分配 [英] Mass assignment on construction from within ruby

查看:146
本文介绍了从红宝石内部施工的质量分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆