2014-11-16 1 views
0

EnumerableForwardable mixins를 사용하는 클래스가 있습니다. 비록 #each이 구현 (또는 위임) 되었더라도 #member? (이는 Enumerable과 함께 제공됨)이 제대로 작동하지 않습니다.루비 기본 해시가있는 열거 형

require "forwardable" 
class RestrictedHash 
    include Enumerable 
    extend Forwardable 

    def_delegators :@hash, :[], :[]=, :each 

    def initialize 
    @hash = {} 
    end 
end 

r_h = RestrictedHash.new 
r_h[:a] = [] 
r_h.member?(:a)  #=> false 
r_h.member?(:a, []) #=> Wrong number of arguments (2 for 1) 
r_h.member?([:a, []]) #=> true 

h = {} 
h[:a] = [] 
h.member?(:a)   #=> true 
h.member?([:a, []]) #=> false 

왜 이러한 동작의 차이점이 있습니까?

답변

1

이유는 Hasheach 방법이 예 @hash 위해 이렇게 키 쌍의 값을 얻을 수 있다는 것이다 :이 Enumerablemember?의 구현 each을 사용하는 경우에 있는지 확인하는 것을 의미

irb(main):001:0> h = {} 
=> {} 
irb(main):002:0> h[:a] = [] 
=> [] 
irb(main):003:0> h.each { |i| puts i.inspect } 
[:a, []] 

지정된 값은 성공적으로 ([:a, []]을 찾을 수 있지만 키는 :a이 아닙니다.

Hash 클래스에서 member?implemented to call rb_hash_has_key입니다.

+0

해시가 "인터페이스"Enumerable을 구현하더라도 실제로 Enumerable을 포함하는 대신 메서드를 구현합니까? – cenouro

+0

정확한 내용이 확실하지 않습니다. 간단히 말해 MRI (Ruby의 참조 구현) 인'Hash'는 Ruby 코드가 아닌 C로 구현되고 Enumerable의 모든 메소드는 링크 된 소스에 C 구현을 가지고 있습니다. GitHub에서이 코드를 확인해 보면'rb_include_module (rb_cHash, rb_mEnumerable)'행에 실제로 구현이 추가되는지 아니면'Enumerable'이'Hash.ancestors'에 나열되는지 확실하지 않습니다. 'Hash'는'Enumerable'을 포함하는 클래스로 취급 될 수 있습니다. 미안하지만 결정적인 것은 아닙니다! – mikej

+1

어떤 메소드가 대체되었는지 분석하기위한 스크립트를 만들었습니다. Hash는'Enumerable '에서 많은 메소드를 가지고 있지만'Enumerable'에 포함 된 메소드를 오버라이드합니다. 이 스크립트는 다음과 같습니다 : 'Enumerable.instance_methods.each {| method | puts "# {method} # {Hash.new.method (method.to_sym) .owner}"}' – cenouro