2017-04-05 6 views
2

Ruby는 타입이 지정되지 않은 언어이므로 루비는 오히려 동성애입니다. 예 :Ruby 다른 유형의 객체에 대한 멤버십 설정

class Test 
    attr_reader :field 

    def initialize(f) 
     @field = String(f) 
    end 

    def ==(other) 
     field == String(other) 
    end 

    def eql?(other) 
     field.eql? String(other) 
    end 

    def hash 
     field.hash 
    end 

    def to_s 
     field 
    end 
end 

s = Set.new([Test.new('string')]) 
# => [#<Test:0x007fc97da17ea0 @field="string">] 

puts Test.new('string').eql?(Test.new('string')) 
# true 

puts Test.new('string').hash == Test.new('string').hash 
# true 

puts s.member? Test.new('string') 
# true 

puts s.member? Test.new('other') 
# false 

puts Test.new('string') == 'string' 
# true 

puts Test.new('string').eql? 'string' 
# true 

puts Test.new('string').hash == 'string'.hash 
# true 

그러나, 루비 내부 검사를 몇 가지 유형을 적용처럼

puts s.member? 'string' 
# false 

이 보인다. 이게 사실인가요?

답변

3

귀하의 주요 문제가 String#eql?입니다 : 주위에 다른 방법을 사용하는 경우 귀하의 예제가 작동

rb_str_eql(VALUE str1, VALUE str2) 
{ 
    if (str1 == str2) return Qtrue; 
    if (!RB_TYPE_P(str2, T_STRING)) return Qfalse; 
    return str_eql(str1, str2); 
} 

참고 : 맞아

puts Test.new('string').eql? 'string' 
# true 
puts 'string'.eql? Test.new('string') 
# false 

, 일부 내부 유형 검사있을 것 같습니다 :

s = Set.new(['string']) 
puts s.member? Test.new('string') 
# true 

이 동작을 실제로 수행하려는 경우 원숭이 패치 String#eql?가 수 :

module TestStringEquality 
    def eql?(other) 
    other.is_a?(Test) ? other.eql?(self) : super 
    end 
end 

s = Set.new([Test.new('string')]) 
puts s.member? 'string' 
# false 

class String 
    prepend TestStringEquality 
end 

puts s.member? 'string' 
# true 

조심,이 방법은 아마 모든 보석에 사용됩니다.

마지막으로 Set은 순수한 Ruby 구현이며 Hash을 백엔드로 사용한다는 것을 기억하십시오. 정보와 문서를 쉽게 얻을 수 있습니다.

+1

덜 침략적 인 패치에 대해 유형 검사 ('other.is_a? Test')를 추가 할 수 있습니다. – Stefan

+0

작동하는 것 : http://ideone.com/7fibfL – Stefan

+1

아마도 모듈로 메소드를 옮기고'refine' 또는'prepend'를 사용하여 적절한'super' 메소드를 사용합니다. 그런 다음 비교를 'other'(역순)로 위임하거나 'super'를 호출 할 수 있습니다. 즉, 'other.is_a? (Test)? 다른 사람 .eql? (self) : super' – Stefan