2

在一个简单的 Ruby 示例中,我收到了一个 irb 中没有发生的错误。

name = "Joe"
def say_hi
  "\"Hi there!\" said #{self}"
end
response = name.say_hi
puts response

此代码应返回“您好!” 乔说。

它在 irb 中工作得非常好。但是,当我尝试将相同的代码放入文件并运行该文件时,我收到此错误:

say_hi.rb:8:in `<main>': private method `say_hi' called for "Joe":String (NoMethodError)

关于为什么会发生这种情况的任何建议?

4

5 回答 5

3

你快到了:

name = "Joe"
def name.say_hi
  "\"Hi there!\" said #{self}"
end

response = name.say_hi
puts response
#=> "Hi there!" said Joe

def name.say_hi将在您上定义一个单例方法name,因此您可以按预期调用它:name.say_hi

于 2012-11-26T23:00:04.787 回答
1

say_hi您为mainnot for定义了方法name。如果你想为 name 定义它,你应该这样做:

class << name
  def say_hi
    %["Hi there!" said #{self}]
  end
end
于 2012-11-26T23:00:22.713 回答
1

这是因为当您在 IRB 中定义方法时,它们成为系统中所有对象的实例方法。包括那个字符串“Joe”。但是当您正常运行代码时,它不会发生。您必须自己将该方法添加到 String 类。像这样,例如:

class String
  def say_hi
    "\"Hi there!\" said #{self}"
  end
end

"Joe".say_hi # => "\"Hi there!\" said Joe"
于 2012-11-26T23:00:47.020 回答
1

You defined a variable 'name` and a method. But there is no connection between them.

You could extend String:

name = "Joe"
class String
  def say_hi
    "\"Hi there!\" said #{self}"
  end
end
response = name.say_hi
puts response

Or you define the method for the object nameitself (see slivus answer)

Or you may define your method in a module and extend your variable.

The advantage: You may also use the module for other object.

Example:

module Hi
  def say_hi
    "\"Hi there!\" said #{self}"
  end
end

name = "Joe"
name.extend(Hi)
puts name.say_hi

name2 = "Jane"
name2.extend(Hi)
puts name2.say_hi
于 2012-11-26T23:01:54.600 回答
1

在 irb 内部(和顶级范围内),self 设置为 main 类型,即 Object 类型。此处对此进行了描述:Ruby中的“主要”是什么?. 所以 :say_hi 是在 Object 上定义的实例方法,因此所有接收者都会响应它,包括 String 的实例,例如“Joe”。

尝试添加:

puts "Private methods: " + Object.private_methods.grep(/say/).inspect
puts "Public methods: " + Object.public_methods.grep(/say/).inspect

您会看到 IRB 向 Object 添加公共方法,而脚本作为私有方法添加,因此不能使用显式接收器调用。

于 2012-11-26T23:12:45.447 回答