루비에서 method_missing
메서드를 정의 할 때주의해야 할 사항이 있습니까? 상속, 예외 던지기, 퍼포먼스 또는 그 밖의 다른 것들과의 명백한 상호 작용이 있는지 궁금합니다.루비에서 gotchas를 method_missing
답변
다소 명백한 것 : method_missing
을 다시 정의하면 항상 respond_to?
을 다시 정의하십시오. method_missing(:sym)
이 작동하면 respond_to?(:sym)
은 항상 true를 반환해야합니다. 이 라이브러리에는 많은 라이브러리가 있습니다.
나중에
:예 : 당신이 방법 이름을 예상 할 수 있다면, 동적 method_missing는 성능 저하를 초래하기 때문에 method_missing에 의존하는 것보다 그들에게 선언하는 것이 좋습니다
# Wrap a Foo; don't expose the internal guts.
# Pass any method that starts with 'a' on to the
# Foo.
class FooWrapper
def initialize(foo)
@foo = foo
end
def some_method_that_doesnt_start_with_a
'bar'
end
def a_method_that_does_start_with_a
'baz'
end
def respond_to?(sym, include_private = false)
pass_sym_to_foo?(sym) || super(sym, include_private)
end
def method_missing(sym, *args, &block)
return foo.call(sym, *args, &block) if pass_sym_to_foo?(sym)
super(sym, *args, &block)
end
private
def pass_sym_to_foo?(sym)
sym.to_s =~ /^a/ && @foo.respond_to?(sym)
end
end
class Foo
def argh
'argh'
end
def blech
'blech'
end
end
w = FooWrapper.new(Foo.new)
w.respond_to?(:some_method_that_doesnt_start_with_a)
# => true
w.some_method_that_doesnt_start_with_a
# => 'bar'
w.respond_to?(:a_method_that_does_start_with_a)
# => true
w.a_method_that_does_start_with_a
# => 'baz'
w.respond_to?(:argh)
# => true
w.argh
# => 'argh'
w.respond_to?(:blech)
# => false
w.blech
# NoMethodError
w.respond_to?(:glem!)
# => false
w.glem!
# NoMethodError
w.respond_to?(:apples?)
w.apples?
# NoMethodError
. 예를 들어,이 구문을 사용하여 데이터베이스 뷰에 액세스 할 수 있도록 데이터베이스 핸들을 확장하고 싶어한다고 가정
selected_view_rows = @dbh.viewname(:column => value, ...)
대신의 이름으로 데이터베이스에 메소드 이름을 데이터베이스 핸들에 method_missing에 의존하고 파견 이상 뷰를 사용하면 데이터베이스의 모든 뷰를 미리 확인한 다음 반복하여 @dbh에 "viewname"메서드를 만들 수 있습니다.
Pistos's point에 건물 : method_missing
은 적어도 내가 시도한 모든 Ruby 구현을 호출하는 일반 메소드보다 훨씬 느립니다. 그는 method_missing
로 전화하는 것을 피할 수있을 때를 예견하는 것이 옳습니다.
모험을 느끼는 경우, Ruby의 잘 알려지지 않은 Delegator 클래스를 확인하십시오.
메소드 누락 메소드가 특정 메소드 이름만을 찾고있는 경우, 찾고있는 것을 찾지 못하면 super를 호출하여 다른 메소드 누락이 해당 메소드를 수행 할 수 있도록하십시오.
예 - 그렇지 않으면 메서드 호출이 자동으로 실패하고 오류가 없는데도 메서드가 작동하지 않는 이유를 파악하는 데 몇 시간을 소비하게됩니다. (그런 일은하지 않았을 것입니다) – PhillipKregg
또 다른 잡았다 :
method_missing
다르게 사이 obj.call_method
및 obj.send(:call_method)
동작합니다. 본질적으로 이전의 메소드는 모든 비공개 및 비 정의 메소드를 놓치고 나중에는 개인 메소드를 놓치지 않습니다.
따라서 send
을 통해 개인 방법을 호출 할 때 method_missing
은 전화를 걸러 내지 않습니다.
제임스의 대답은 현대 루비에, 중대하다하지만 (1.9+), 마크 - 앙드레는 말처럼, 당신은 방법 자체를 반환 method(:method_name)
처럼, 당신은 respond_to?
위에 다른 방법에 액세스 할 수 있기 때문에 respond_to_missing?
를 재정의 할 .
예, 정의 된 다음 클래스 : method_missing
를 오버라이드 (override) 할 때
irb(main):015:0> u = UserWrapper.new
=> #<UserWrapper:0x00007fac7b0d3c28 @json_user={:first_name=>"Jean", :last_name=>"Dupont"}>
irb(main):016:0> u.first_name
=> "Jean"
irb(main):017:0> u.respond_to?(:first_name)
=> true
irb(main):018:0> u.method(:first_name)
=> #<Method: UserWrapper#first_name>
irb(main):019:0> u.foo
NoMethodError (undefined method `foo' for #<UserWrapper:0x00007fac7b0d3c28>)
그래서, 항상 respond_to_missing?
을 정의의
class UserWrapper
def initialize
@json_user = { first_name: 'Jean', last_name: 'Dupont' }
end
def method_missing(sym, *args, &block)
return @json_user[sym] if @json_user.keys.include?(sym)
super
end
def respond_to_missing?(sym, include_private = false)
@json_user.keys.include?(sym) || super
end
end
결과.
- 1. method_missing 재정의
- 2. 얼랭 (Erlang)과 method_missing
- 3. instance_eval, define_method 및 method_missing
- 4. 어떻게이`method_missing`을 작성합니까?
- 5. 레이크 작업을위한 "method_missing"이 있습니까?
- 6. 레일 method_missing 및 activerecord 클래스 캐싱
- 7. 어떻게 루비에서
- 8. 사용은 루비에서
- 9. 하위 클래스의 루비에서 Fixnum
- 10. 루비에서 이벤트 어떻게?
- 11. 루비에서`call_user_func_array`를 달성하기
- 12. 루비에서 DOCX를 DOC로 변환
- 13. 루비에서 날짜 계산
- 14. 루비에서 XSLT 처리하기
- 15. 루비에서 컴포지션 사용
- 16. 루비에서 가장 짧은 hex2bin?
- 17. 루비에서 클래스 관계 설명하기
- 18. 시도 루비에서 그루비
- 19. 루비에서 어떻게 작동하는지 확인
- 20. 모의 시스템 호출 루비에서
- 21. 루비에서 배열 정렬
- 22. 루비에서 run_once 란 무엇입니까?
- 23. 루비에서 ldap 통합
- 24. 루비에서 날짜 클래스 확장하기
- 25. 루비에서 캐스트를 가짜로 만들었습니까?
- 26. 어떻게합니까? 루비에서 일해?
- 27. 루비에서 심볼을 뺍니다.
- 28. 루비에서 앞에 0이있는 범위
- 29. 루비에서 목록 구현?
- 30. 루비에서 모듈 재정의?
재미 있습니다."정상적인"메서드와 "동적 인"메서드 (method_missing을 통해 구현)로 구성된 클래스에 대해 어떻게 구현하겠습니까? –
@Christoph : 당신의'pass_sym_to_foo? '메쏘드는이 요청을 처리하려고 시도하는지'super'의'method_missing'에게 넘겨 줄지 결정하는 일반적인'handle'메쏘드가됩니다. –
Ruby 1.9.2에서'respond_to_missing? '을 재정의하는 것이 더 좋습니다. 내 블로그 게시물을 참조하십시오. http://blog.marc-andre.ca/2010/11/methodmissing-politely.html –