我正在尝试理解Ruby,而且我不清楚Ruby如何将方法名称转换为Symbol
?
在方法定义中,我们给它命名为meth
module Mod
def meth
puts 'm'
end
end
但是,如果我们想检查方法是否存在,我们会将符号:meth
作为参数传递给method_defined
Mod.method_defined?(:meth)
=> true
请帮助我理解,这是如何工作的?
答案 0 :(得分:2)
这是由于ruby的方法调用语法:您可以仅通过引用其名称来调用方法,而无需使用括号()
之类的任何其他语法。
现在,如果method_defined?
方法将方法本身作为参数,那么在没有实际调用方法的情况下将无法这样做,从而在方法不存在时产生错误:
Mod.method_defined?(meth)
#=> NameError: undefined local variable or method `meth'
使用符号时,不会发生调用,它通常只是实例化而不会产生任何错误。在窗帘后面,method_defined?
可以查找符号引用的名称是否存在方法,而不会产生任何错误。
答案 1 :(得分:1)
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)
你看到天才了吗?