在一个简单的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)
有关为何会发生这种情况的任何建议吗?
答案 0 :(得分: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
答案 1 :(得分:1)
您为say_hi
定义的方法main
不是name
。如果你想为名称定义它,你应该这样做:
class << name
def say_hi
%["Hi there!" said #{self}]
end
end
答案 2 :(得分:1)
这是因为当您在IRB中定义方法时,它们将成为系统中所有对象的实例方法。包括那个字符串“乔”。但是当你正常运行代码时,它不会发生。您必须自己将该方法添加到String类。像这样,例如:
class String
def say_hi
"\"Hi there!\" said #{self}"
end
end
"Joe".say_hi # => "\"Hi there!\" said Joe"
答案 3 :(得分:1)
您定义了变量'name`和方法。但他们之间没有联系。
你可以扩展String:
name = "Joe"
class String
def say_hi
"\"Hi there!\" said #{self}"
end
end
response = name.say_hi
puts response
或者您为对象name
本身定义方法(请参阅slivus answer)
或者您可以在模块中定义方法并扩展变量。
优点:您也可以将该模块用于其他对象。
示例:
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
答案 4 :(得分:1)
在irb内部(在顶级范围内),self设置为main类型为Object。这在此描述:What is "main" in 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,而脚本作为私有方法添加,因此无法使用explict接收器调用。