2012-11-26 6 views
2

간단한 Ruby 예제에서 irb에서는 발생하지 않는 오류가 발생합니다.Ruby의 NoMethodError에 대해 혼동을 느낀 경우

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) 

이런 일이 발생하는 이유에 대해 어떤 제안 : 내가 파일에 동일한 코드를 넣고 파일을 실행하려고 할 때 그러나, 나는이 오류가?

+1

답이 다소 차이가 있지만 궁극적 인 목적은 무엇입니까? 'String'에 메소드 추가하기? 문자열의 해당 인스턴스에? 문자열과 비슷하지만 'Person'과 같이 다른 새로운 유형 중 ... 또는 ...? –

+0

나의 목적은'String'에 메소드를 추가하는 것이 었습니다. 그래도 답장을 보내 주신 모든 분들께 감사드립니다.제 목적에도 불구하고, 나는 행동의 구별을 정말로 알고 싶었습니다. –

답변

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_hiname에 싱글 메소드를 정의하고 예상대로 따라서 당신은 그것을 호출 할 수 있습니다 : 당신은 name 아니 main위한 방법 say_hi을 정의 name.say_hi

1

. 당신이 이름을 정의하려는 경우 당신은 어떻게해야 : 당신이 IRB의 방법을 정의 할 때, 그들은 시스템의 모든 개체에 대한 인스턴스 메서드되기 때문에이 문제가 발생

class << name 
    def say_hi 
    %["Hi there!" said #{self}] 
    end 
end 
1

. 해당 문자열 "조"포함. 그러나 코드를 정상적으로 실행하면 발생하지 않습니다. String 클래스에 메서드를 직접 추가해야합니다. 예를 들면 다음과 같습니다.

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

"Joe".say_hi # => "\"Hi there!\" said Joe" 
1

'name'변수와 메소드를 정의했습니다. 그러나 그들 사이에는 아무런 연관이 없습니다.

당신은 문자열을 확장 할 수 :

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

또는 당신은

(slivus answer 참조) 객체 name 자체를하는 방법을 정의 또는 당신은 모듈에 당신의 방법을 정의하고 변수를 연장 할 수있다.

장점 : 모듈을 다른 개체에도 사용할 수 있습니다.

예 (및 최상위 범위 안에)는, 자기가 입력되는 주된 목적으로 설정된 내부 IRB

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 
1

. 여기에 설명되어 있습니다 : What is "main" in 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 스크립트가 개인 방법으로 추가하고 따라서 EXPLICT 수신기를 호출 할 수 없습니다 반면 Object로 공용 메서드를 추가하는 것을 볼 수 있습니다.

관련 문제