12
class A
   def test
       "Test from instance"
   end
   class << self
       def test
           "Test from class"
       end
    end
end

p A.send(:test)    # "Test from class"
p A.new.method(:test).call  # "Test from instance"

这里的符号按预期工作,但在这里:

s="test"
s1=:s
p s1   # :s

为什么:s在这里打印?我不明白背后的原因。谁能为我解释一下?

4

5 回答 5

18

符号是一种轻量级的字符串(尽管它们不是字符串)。send()andmethod()方法可以采用字符串或符号;一个在内部工作中转换为另一个(不确定是哪个),然后 ruby​​ 执行具有匹配名称的方法。因此A.send(:text)等价于A.text()。如果你有一个名为 的变量methodName = :text,你可以这样做,A.send(methodName)但不能A.methodName()

符号不是变量,因此您不能为符号赋值。在您的示例中,该符号:s与变量无关s(尽管它们具有相同的“名称”,但在其前面加上冒号使其成为符号而不是变量)。您正在为变量分配一个字符串值,s但告诉它打印符号:s,它确实如此。

于 2013-02-06T19:04:24.550 回答
3

来自https://stackoverflow.com/a/1255362/509710

p foo确实 puts foo.inspect,即它打印的值inspect而不是to_s,这更适合调试(因为您可以例如区分1,"1""2\b1",而在没有检查的情况下打印时您无法区分)。

于 2013-02-06T18:52:41.587 回答
2

您将 s1 的值设置为 :s,那么您为什么希望它返回任何不同的值呢?

如果您查看 Object 类的 ruby​​ API,您会看到Object#sendObject#method都将符号作为参数,因此上面的示例也完全符合预期。

于 2013-02-06T18:49:59.313 回答
2

符号只是一种特殊的类似字符串的值,运行时处理它比普通字符串更有效。而已。它们不是方法或变量或类似的东西。

当你这样做时A.send(:test),你所做的就是说“嘿,A,调用名为'test'的方法”。您不是发送方法本身,而是发送名称;内部的逻辑send负责查找要调用的实际方法。

当你要求方法 with 时也是如此A.new.method(:test)。您传递给method的只是名称“test”,而不是使用该名称定义的方法。取决于method使用名称并找到实际的方法,以便它可以返回它,而这就是你正在做的返回值 - 一个 Method 对象call。你不能call对像 一样的符号做:test,因为它只是一个名字。

于 2013-02-06T19:09:47.723 回答
2
s="test"
s1=:s
p :s.object_id  #137448
p s.object_id   #77489950
p s1.object_id  #137448

我现在已经明白了。我正在分配一个符号,但期待一个字符串。

于 2013-02-06T19:09:53.287 回答