2015-01-09 11 views
14

मुझे परिभाषा के क्रम में स्विफ्ट में enums की तुलना करने के तरीके पर दस्तावेज़ीकरण खोजने/समझने में परेशानी हुई है। विशेष रूप से जब मैं एक गणन जैसेस्विफ्ट गणना आदेश और तुलना

enum EnumType { 
    case First, Second, Third 
} 

स्विफ्ट मुझसे सीधे आदेश से enums तुलना करने के लिए अनुमति नहीं है,

let type1 = EnumType.First 
let type2 = EnumType.Second 
if type1 < type2 {println("good")} // error 

इस तरह के रूप में यह संकलन त्रुटि उत्पन्न बनाने के "तर्क सूची के साथ आह्वान नहीं कर सकता '<' {EnumType, EnumType} प्रकार के के। तो एकमात्र समाधान मैंने पाया भार के रूप में अपने खुद के तुलना ऑपरेटरों, इस तरह के

enum EnumType : Int { 
    case First = 0, Second, Third 
} 

func <(a: EnumType, b: EnumType) -> Bool { 
    return a.rawValue < b.rawValue 
} 

let type1 = EnumType.First 
let type2 = EnumType.Second 
if type1 < type2 {println("good")} // Returns "good" 

के रूप में यह लिखने के लिए सब कुछ ठीक एक है "भारी वजन" enums के लिए अच्छा है जो मेरे आवेदन में बहुत अधिक उपयोग और मूल्य है, लेकिन उन सभी ऑपरेटरों को अधिभारित करना जिन्हें मैं उपयोग करना चाहूंगा, वे 'हल्के वजन' enums के लिए अत्यधिक बोझिल लगते हैं जिन्हें मैं कुछ लोगों को आदेश देने के लिए फ्लाई पर परिभाषित कर सकता हूं एक छोटे मॉड्यूल के लिए स्थिरांक।

क्या मेरे प्रोजेक्ट में परिभाषित प्रत्येक एनम प्रकार के लिए बॉयलरप्लेट अधिभार कोड लिखने के बिना ऐसा करने का कोई तरीका है? इससे भी बेहतर, क्या कुछ ऐसा है जो मुझे स्विफ्ट करने के लिए याद आ रही है, सरल एनम के लिए तुलनात्मक ऑपरेटरों को स्वचालित रूप से प्रदान करता है जिनमें संबंधित प्रकार नहीं हैं, यानी। जो इंटी के रूप में टाइप या टाइप किए गए हैं? स्विफ्ट जानता है कि इंट्स की तुलना कैसे करें, तो यह एनम इंट्स की तुलना क्यों नहीं कर सकता?

+1

आप [इस जवाब] (http://stackoverflow.com/a/27094973/148357) में वर्णित 'हैशवैलू 'संपत्ति का उपयोग कर सकते हैं। पिछले बयान :) – Antonio

उत्तर

35

जब तक आप अपना enum अंतर्निहित प्रकार देते हैं, यह प्रोटोकॉल RawRepresentable के अनुरूप होगा।

इसका मतलब है आप किसी भी प्रकार के कच्चे प्रदर्शनीय है कि के लिए एक सामान्य तुलना ऑपरेटर लिख सकते हैं, और एक कच्चे प्रकार है कि तुलनीय है, इसलिए जैसे:

func <<T: RawRepresentable where T.RawValue: Comparable>(a: T, b: T) -> Bool { 
    return a.rawValue < b.rawValue 
} 

जो मतलब होगा अपने enum स्वचालित रूप से एक < होगा ऑपरेटर:

enum E: Int { // this would work with Double and String also 
    // btw, no need to give a seed value of 0, 
    // that happens automatically for Ints 
    case A, B, C, D, E 
} 

E.A < E.C // returns true 

बॉयलरप्लेट का केवल थोड़ा तुम अब भी करना होगा टैग Comparable के रूप में अपने enum मामले में आप सामान्य एल्गोरिदम कि आवश्यकता के साथ उपयोग करना चाहते हैं कि:

+०१२३५१६४१०
extension E: Comparable { } 
// (no need for anything else - requirements are already fulfilled) 

let a: [E] = [.C, .E, .A] 
let b = sorted(a) 
// b will now be [.A, .C, .E] 

यह Comparable के अनुरूप भी यह <=, >, और >= ऑपरेटरों स्वचालित रूप से (मानक पुस्तकालय द्वारा आपूर्ति) दे देंगे बनाना।

+7

पढ़ लें या फिर आप enum ई के रूप में enum लिख सकते हैं: इंट, तुलनीय {} .., वहाँ बाहर लटक एक यादृच्छिक विस्तार लाइन होने IMO में कोई भावना। –

+0

क्या यह दृष्टिकोण स्ट्रिंग एनम (उदा। केस "जेड", केस "ए") के लिए सही क्रम देता है? मेरा सुझाव है, तुलना ऑपरेटर "Z"> "ए" लौटाएगा, हमारे मामले के लिए क्या गलत है। – brigadir

6

यह कुछ हद तक एक ही जवाब है जैसा कि ओपी ने खुद को प्रस्तावित किया था। इसमें प्रत्येक enum के लिए बॉयलरप्लेट कोड का थोड़ा सा हिस्सा शामिल है जिसे आप तुलनात्मक बनाना चाहते हैं, लेकिन मैं इसे कुछ बाहरी जादू कार्य करने से पसंद करता हूं जो सभी enums के लिए तुलनीय प्रदान करता है। इससे समस्याएं पैदा हो सकती हैं यदि आप एक प्रोग्राम से दूसरे प्रोग्राम में त्वरित कॉपी-पेस्ट करते हैं, और फिर enum काम नहीं करता है और आप याद नहीं कर सकते क्यों।

public enum LogLevel: Int, Comparable { 
    case verbose 
    case debug 
    case info 
    case warning 
    case error 
    case severe 

    // Implement Comparable 
    public static func < (a: LogLevel, b: LogLevel) -> Bool { 
     return a.rawValue < b.rawValue 
    } 
} 

संपादित करें:

यह @JasonMoore द्वारा एक टिप्पणी के जवाब में है।

तुलनात्मक के लिए == की आवश्यकता नहीं है। यह Equatable द्वारा आवश्यक है, और स्विफ्ट मानक पुस्तकालय स्वचालित रूप से अधिकांश प्रकार के enums के लिए Equatable प्रदान करता है।

http://www.jessesquires.com/blog/swift-enumerations-and-equatable/

के रूप में>, < = और> =, एप्पल प्रलेखन का कहना है कि वे तुलनीय के लिए आवश्यक हैं, लेकिन एक डिफ़ॉल्ट कार्यान्वयन प्रदान की जाती है कि (== और < के उपयोग पर आधारित, मुझे लगता है) ।

https://developer.apple.com/documentation/swift/comparable

यहाँ है कि मैं आईबीएम स्विफ्ट सैंडबॉक्स में भाग गया कोड का एक सा है - यह संकलित करता है तथा उपरोक्त परिभाषा के साथ ठीक चलाता है।

let a : LogLevel = LogLevel.verbose 
let b : LogLevel = LogLevel.verbose 
let c : LogLevel = LogLevel.warning 

print(a == b) // prints true 
print(a > c) // prints false 
print(a <= c) // prints true 
+1

तुलनात्मक के अनुरूप आपको '<=', '> = 'और'> 'विधियों को जोड़ने की आवश्यकता है। यह बॉयलरप्लेट की एक कष्टप्रद राशि है। –

+1

@JasonMoore कृपया जो मैंने जोड़ा है उसे देखें। – RenniePet

+2

आप सही हैं। 'Equatable' स्वचालित रूप से enums पर स्वचालित रूप से जोड़ा जाता है (जब तक आपके पास एक चर के साथ enum केस नहीं है)। और आप केवल '<'लागू करके तुलनात्मक के अनुरूप हो सकते हैं। इसे स्पष्ट करने के लिए धन्यवाद। (क्या मुझे उपरोक्त मेरी टिप्पणी हटा दी जानी चाहिए?) –

संबंधित मुद्दे