方法名如何在Ruby中转换为符号?

时间:2013-08-16 06:47:44

标签: ruby

我正在尝试理解Ruby,而且我不清楚Ruby如何将方法名称转换为Symbol

在方法定义中,我们给它命名为meth

module Mod
  def meth
    puts 'm'
  end
end

但是,如果我们想检查方法是否存在,我们会将符号:meth作为参数传递给method_defined

Mod.method_defined?(:meth)
=> true 

请帮助我理解,这是如何工作的?

5 个答案:

答案 0 :(得分:2)

这是由于ruby的方法调用语法:您可以仅通过引用其名称来调用方法,而无需使用括号()之类的任何其他语法。

现在,如果method_defined?方法将方法本身作为参数,那么在没有实际调用方法的情况下将无法这样做,从而在方法不存在时产生错误:

Mod.method_defined?(meth) 
#=> NameError: undefined local variable or method `meth'

使用符号时,不会发生调用,它通常只是实例化而不会产生任何错误。在窗帘后面,method_defined?可以查找符号引用的名称是否存在方法,而不会产生任何错误。

答案 1 :(得分:1)

Module#method_defined?

  

method_defined?(符号)→true或false

     

method_defined?(string)→true或false

     

如果命名方法由mod(或其包含的模块定义,并且如果mod是类,其祖先)定义,则返回true。公共和受保护的方法是匹配的。 字符串参数将转换为符号。

这意味着 - method_defined?方法始终期望 symbol 作为其参数,但如果使用 string ,则使用{{在内部将其转换为符号1}}。

答案 2 :(得分:1)

方法不是“变成”一个符号,只是它可以用符号引用。

当我们从ObjectSpace.methods中查看方法集合时,我们看到对象被称为符号。

这是有道理的,因为Ruby中的符号是高效的,因为只有一个对象是该符号,它们是不可变的,它可以根据其上下文引用它需要的内容,指的是范围和什么是“自我” “现在是。”

换句话说,无论引用何处,名为:to_s的符号都将是相同的符号。它的object_id将始终相同,但它可能引用Array的to_s方法,甚至是名为to_s的局部变量。

答案 3 :(得分:1)

  

我不清楚Ruby如何将方法名称转换为:symbol?

这就是Method#name的工作方式,它将方法的名称作为符号返回:

m = "foo".method(:size)     #=> #<Method: String#size>
m.name                      #=> :size
m.call                      #=> 3

所有引用其他方法的方法通常都是这样的。例如,Object#methods返回一组方法名称:

"foo".methods
#=> [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, ...]
  

在方法定义中,我们将其命名为meth ...但如果我们想要检查,是否存在任何方法,我们会将method_defined符号:meth

meth将是对变量或其他方法的引用,而:meth只是一个符号:

meth = :foo
Mod.method_defined? meth   #=> false, equivalent to Mod.method_defined? :foo
Mod.method_defined? :meth  #=> true

答案 4 :(得分:1)

标识符也需要存储在内存中。所有语言都以某种形式或其他形式存储方法名称,类名称。他们只是不像Ruby这样访问它们。 类名存储为常量。方法名称存储为符号。没有任何东西可以转换成符号。它始终存储为符号。这使得以下成为可能:

1.send(:+, 3) # exactly same as 1+3

这也意味着您实际上可以接受来自用户的名称并执行该特定方法。您始终可以通过switch / if-else执行此操作,但这确实从功能中删除了一个层。 例如

case option
  when '+'
    variable1 + variable2
  when '-'
    variable1 - variable2
  when '*'
    variable1 * variable2
  when '/'
    variable1 / variable2
end

相比
variable1.send(option, variable2)

你看到天才了吗?