#符号的含义

时间:2013-07-19 13:09:00

标签: ruby methods syntax

我的代码在#部分中有一个class_eval符号。这对我来说很陌生,这是什么意思?

class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s # make sure it's a string
    attr_reader attr_name # create the attribute's getter
    attr_reader attr_name+"_history" # create bar_history getter
    class_eval %Q{
def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
}
  end
end

3 个答案:

答案 0 :(得分:4)

此功能称为字符串插值。它实际上做的是用#{attr_name}替换attr_name实际值。您发布的代码显示了一个用例 - 当您想在运行时使用具有通用名称的变量时。

然后更常使用的用例如下:

您可以这样使用字符串:"Hello, #{name}!"#{name}将自动替换 - 这是非常方便的功能。语法糖。

但请注意代码中的%Q - 这会将以下代码转换为字符串,然后传递给class_eval并在那里执行。详细了解here。没有它,它当然不会起作用。

答案 1 :(得分:2)

  

为什么下一个代码在class_eval中有#?

这是字符串插值。

一个例子:

x = 12
puts %Q{ the numer is #{x} }
# >>  the numer is 12 
  

%Q Here

     

当你在字符串中有更多的引号字符时,这是双引号字符串的替代方法。而不是在它们前面加上反斜杠。

答案 2 :(得分:2)

def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end

如果attr_name变量等于,请说"params"。这实际上会变成这样:

def params=(attr_name)
@params = attr_name
@params_history = [nil] if @params_history.nil?
@params_history << attr_name
end

为什么会这样?因为称为String插值的东西。如果在String中写#{something},则会在该String中评估并替换something

为什么上述代码即使不在字符串中也能正常工作?

答案是,因为它!

Ruby为您提供了不同的处理方式,并且对于某些文字有一种替代语法,如下所示:%w{one two three}其中{}可以是任何分隔符,只要您使用相同的分隔符或相应的结束。所以它可能是%w\one two three\%w[one two three],它们都会有效。

那个,%w用于数组,%Q用于双引号字符串。如果你想看到所有这些,我建议你看看这个:http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

现在,在那段代码中

class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s # make sure it's a string
    attr_reader attr_name # create the attribute's getter
    attr_reader attr_name+"_history" # create bar_history getter
    class_eval %Q{ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # STRING BEGINS
def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # STRING ENDS
  end
end

我们可以看到字符串插值的整个部分位于%Q{ }内。这意味着整个块是一个大的双引号字符串。这就是为什么在将String发送到eval之前,String插值将成功完成它的工作。