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

irb 内 (および最上位スコープ内) で、self がオブジェクト型の main に設定されます。これについては、Ruby の「メイン」とは? . つまり、:say_hi は Object で定義されたインスタンス メソッドであるため、すべてのレシーバーは "Joe" などの String のインスタンスを含めてそれに応答します。

追加してみてください:

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

また、IRB はオブジェクトにパブリック メソッドを追加するのに対し、スクリプトはプライベート メソッドとして追加するため、明示的なレシーバーで呼び出すことができないことがわかります。

于 2012-11-26T23:12:45.447 に答える
1

say_hiメソッドfor mainnot for を定義しました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

変数 'name` とメソッドを定義しました。しかし、それらの間に接続はありません。

文字列を拡張できます:

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
于 2012-11-26T23:01:54.600 に答える