2009-12-19 11 views
38

में समानता एक सरल struct की तरह वर्ग के लिए लागू करने के लिए सही तरीका क्या है आदि ताकि अच्छी तरह से सेट में वर्ग खेलने के उदाहरण, हेश,माणिक

संपादित

इसके अलावा

, क्या समानता लागू करने के लिए जब आप आधारित तुलना करना चाहते हैं एक अच्छा तरीका है राज्य पर जो वर्ग के बाहर खुलासा नहीं है? उदाहरण के लिए:

class Lady 
    attr_accessor :name 

    def initialize(age) 
    @age = age 
    end 
end 
यहाँ

मैं खाते में @age लेने के लिए मेरी समानता विधि चाहते हैं, लेकिन लेडी ग्राहकों को उसकी उम्र का खुलासा नहीं करता। क्या मुझे इस स्थिति में example_variable_get का उपयोग करना होगा?

+0

([यह एक अच्छा writeup इन और परिभाषित करने वस्तु समानता के बहिष्कार की तुलना है] http://www.skorks.com/2009/09/रूबी-समानता-और-वस्तु-तुलना /) – ennuikiller

उत्तर

61

एक से अधिक राज्य परिवर्तनीय वस्तुओं वाले ऑब्जेक्ट्स के लिए तुलना ऑपरेटर को सरल बनाने के लिए, एक विधि बनाएं जो सभी ऑब्जेक्ट की स्थिति को सरणी के रूप में लौटाती है। तो बस दो राज्यों की तुलना: इसके अलावा

class Thing 

    def initialize(a, b, c) 
    @a = a 
    @b = b 
    @c = c 
    end 

    def ==(o) 
    o.class == self.class && o.state == state 
    end 

    protected 

    def state 
    [@a, @b, @c] 
    end 

end 

p Thing.new(1, 2, 3) == Thing.new(1, 2, 3) # => true 
p Thing.new(1, 2, 3) == Thing.new(1, 2, 4) # => false 

, यदि आप एक हैश कुंजी के रूप में प्रयोग करने योग्य होने के लिए अपने वर्ग के उदाहरण चाहते हैं, तो जोड़ें:

alias_method :eql?, :== 

    def hash 
    state.hash 
    end 

ये सार्वजनिक करने की आवश्यकता है।

+2

मुझे वास्तव में राज्य सरणी की तुलना में ऑब्जेक्ट की तुलना करके ऑब्जेक्ट की तुलना करने की इस चाल पसंद है। –

1

आमतौर पर == ऑपरेटर के साथ।

def == (other) 
    if other.class == self.class 
    @name == other.name && @num_stripes == other.num_stripes 
    else 
    false 
    end 
end 
+0

धन्यवाद। हालांकि मुझे लगता है कि यदि आप केवल == को परिभाषित करते हैं तो वर्ग के उदाहरण हैंश और सेट में अपेक्षित व्यवहार नहीं करेंगे। –

+0

इसके अलावा, मैं/सोच/वह == टाइप समानता की जांच नहीं कर रहा है (जैसा कि आपका उदाहरण कर रहा है)। यही ईकएल है? ऐसा करना है। उस पर गलत हो सकता है। –

+0

व्यवहार केवल तभी बदलता है जब आप इसे अलग करते हैं, पीट। आखिरकार मैंने 'true == true' (और' 1 + 1 == 2') की जांच की है, फिर भी 'true' ... –

12

एक ही बार में सभी अपने उदाहरण चर समानता परीक्षण करने के लिए:

def ==(other) 
    other.class == self.class && other.state == self.state 
end 

def state 
    self.instance_variables.map { |variable| self.instance_variable_get variable } 
end 
+3

यह वास्तव में बेहतर तरीका है क्योंकि यह सुनिश्चित करने के लिए एक लंबा रास्ता तय करता है कि आप किसी भी चर को गलती से नहीं छोड़ रहे हैं। अब, प्रत्येक इंस्टेंस वैरिएबल का स्वचालित रूप से उपयोग करने के कुछ अनपेक्षित परिणाम भी हो सकते हैं, लेकिन मुझे यकीन नहीं है और यह तब तक नहीं पता जब तक कि यह मुझे एक दिन आश्चर्य न करे। – WattsInABox

+0

यह सच है, आप उन विशेष मामलों के लिए 'केवल' या 'छोड़कर' जैसे वैकल्पिक पैरामीटर जोड़ सकते हैं। – jvenezia