답변:
일부 클래스 (예 : 표준 라이브러리의 소켓 클래스) send
는 관련이없는 자체 메서드를 정의합니다 Object#send
. 따라서 모든 클래스의 객체로 작업하려면 다음을 사용해야합니다.__send__
하려면 안전한면에 있어야합니다.
이제 그 질문이 남았습니다. 왜 그런지 send
아닌지 __send__
. 단지이 있다면 __send__
이름이 send
혼동없이 다른 클래스에 의해 사용될 수 있습니다. 그 이유는 즉 send
최초의 존재 만 나중에는 이름이 실현되었다 send
그래서,도 유용하게 다른 상황에서 사용될 수있다 __send__
(무슨 일이 있었 같은 일이이 추가되었다 id
및 object_id
방법에 의해).
public_send
종종 바람직하다, send
어쨌든.
당신이 경우 정말 필요 send
정상적으로 할 것처럼 행동하려면 사용해야 __send__
은 (는 안된다) 오버라이드 (override) 할 수 없기 때문에. 사용 __send__
은 조작하는 클래스가 어떤 메소드를 정의하는지 모르는 경우 메타 프로그래밍에 특히 유용합니다. 재정의했을 수 있습니다 send
.
손목 시계:
class Foo
def bar?
true
end
def send(*args)
false
end
end
foo = Foo.new
foo.send(:bar?)
# => false
foo.__send__(:bar?)
# => true
을 무시하면 __send__
, Ruby는 경고를냅니다 :
경고 :`__send__ '를 재정의하면 심각한 문제가 발생할 수 있습니다
재정의하는 send
것이 유용한 경우 는 메시지 전달, 소켓 클래스 등과 같이 해당 이름이 적절한 경우 가 있습니다.
그렇다에서 무엇을 다른 사람이 이미 당신에게 무엇을 말하는 아래로 비등 send
과 __send__
같은 방법으로 두 개의 별칭, 세 번째에 관심이있을 수 있습니다, somwhat 다른 가능성이다 public_send
. 예:
A, B, C = Module.new, Module.new, Module.new
B.include A #=> error -- private method
B.send :include, A #=> bypasses the method's privacy
C.public_send :include, A #=> does not bypass privacy
업데이트 : 루비 2.1, 이후 Module#include
및 Module#extend
공공 될 방법, 위의 예는 더 이상 작동하지 않을 것 때문에.
send __send__
, 및 public_send 의 주요 차이점은 다음과 같습니다.
__send__
는 기술적으로 Object의 메소드를 호출하는 데 사용되는 것과 동일하지만 가장 큰 차이점은 경고없이 send 메소드를 대체 할 수 있으며 무시할 때 __send__
경고 메시지가 있다는 것입니다경고 : 재정의
__send__
하면 심각한 문제가 발생할 수 있습니다
이는 사용될 컨텍스트를 알 수 없을 때 특히 gem이나 라이브러리에서 충돌을 피하기 위해 항상 __send__
send 대신 사용하십시오 .
__send__
)와 public_send 의 차이점은 send __send__
는 개체의 개인 메서드를 호출 / 호출 할 수 있고 public_send는 호출 할 수 없다는 것입니다.class Foo
def __send__(*args, &block)
"__send__"
end
def send(*args)
"send"
end
def bar
"bar"
end
private
def private_bar
"private_bar"
end
end
Foo.new.bar #=> "bar"
Foo.new.private_bar #=> NoMethodError(private method 'private_bar' called for #Foo)
Foo.new.send(:bar) #=> "send"
Foo.new.__send__(:bar) #=> "__send__"
Foo.new.public_send(:bar) #=> "bar"
Foo.new.send(:private_bar) #=> "send"
Foo.new.__send__(:private_bar) #=> "__send__"
Foo.new.public_send(:private_bar) #=> NoMethodError(private method 'private_bar' called for #Foo)
결국 __send__ 또는 send 대신 private 메소드에 대한 직접 호출을 피하려면 public_send를 사용하십시오.
__send__
하지send
.