2017-05-19 5 views
5

भाषा साथ enums पर एक अगर-बाकी तुलना कैसे करना है: Swift2.3तर्क

उदाहरण के जाने के लिए मैं आप enums

enum Normal { 
    case one 
    case two, three 
} 

enum NormalRaw: Int { 
    case one 
    case two, three 
} 

enum NormalArg { 
    case one(Int) 
    case two, three 
} 

Switch के विभिन्न प्रकार दिखाता हूँ पर इस्तेमाल किया जा सकता सभी तीन enums तो जैसे:

var normal: Normal = .one 
var normalRaw: NormalRaw = .one 
var normalArg: NormalArg = .one(1) 

switch normal { 
    case .one: print("1") 
    default: break 
} 

switch normalRaw { 
    case .one: print(normalRaw.rawValue) 
    default: break 
} 

switch normalArg { 
    case .one(let value): print(value) 
    default: break 
} 

अगर-बाकी बयान हालांकि मैं केवल Normal और ०१२३३०७०१३ के लिए तुलना कर सकते हैं पर, और एक त्रुटि संदेश NormalArg के लिए पता चलता है, तो मैं कोड

द्विआधारी ऑपरेटर '==' प्रकार के ऑपरेंड के लिए लागू नहीं किया जा सकता NormalArg और _

कोड यह नहीं चल सकता उदाहरण:

if normal == .two { // no issue 
    .. do something 
} 

if normalRaw == .two { // no issue 
    .. do something 
} 

if normalArg == .two { // error here (the above message) 
    .. do something 
} 

if normalArg == .one(_) { // error here (the above message) 
    .. do something 
} 

if normalArg == .three { // error here (the above message) 
    .. do something 
} 

कोई विचार? मैं वास्तव में इस कोड के साथ कुछ भी नहीं कर रहा हूं, मैं बस सोच रहा हूं कि हम तुलना क्यों नहीं कर सकते हैं।

उत्तर

19

चाल == साथ वास्तव में नहीं की जाँच करने के बल्कि अपने अगर बयान में एक भी = साथ संयोजन के रूप में case कीवर्ड का उपयोग है।

enum Normal { 
    case one 
    case two, three 
} 

enum NormalRaw: Int { 
    case one = 1 
    case two, three 
} 

enum NormalArg { 
    case one(Int) 
    case two, three 
} 


let normalOne = Normal.one 
let normalRawOne = NormalRaw.one 
let normalArgOne = NormalArg.one(1) 

if case .one = normalOne { 
    print("A normal one") //prints "A normal one" 
} 

if case .one = normalRawOne { 
    print("A normal \(normalRawOne.rawValue)") //prints "A normal 1" 
} 

if case .one(let value) = normalArgOne { 
    print("A normal \(value)") //prints "A normal 1" 
} 

मुद्दा यह है कि स्विफ्ट में आप केवल मुक्त करने के लिए enums के समीकरण प्राप्त अपने enum एक कच्चे प्रकार का उपयोग करता है, तो है: यह एक छोटे से काउंटर शुरुआत में सहज लेकिन सिर्फ if let की तरह, आप इसे करने के लिए बहुत तेजी से आदत हो है या यदि आपके पास कोई संबंधित मूल्य नहीं है (इसे आज़माएं, तो आप दोनों एक ही समय में नहीं हो सकते हैं)। हालांकि स्विफ्ट को पता नहीं है कि संबंधित मूल्यों के मामलों की तुलना कैसे करें - मेरा मतलब है कि यह कैसे हो सकता है?

class Special { 
    var name: String? 
    var special: Special? 
} 

enum SpecialEnum { 
    case one(Special) 
    case two 
} 

var special1 = Special() 
special1.name = "Hello" 

var special2 = Special() 
special2.name = "World" 
special2.special = special1 

SpecialEnum.one(special1) == SpecialEnum.one(special2) //Well...? 

तो अगर आप संबद्ध मूल्यों के साथ enums चाहते हैं, आप Equatable को लागू करना होगा:

Normal.one == .one //true 
Normal.one == .two //false 

NormalRaw.one == .one //true 
NormalRaw.one == .two //false 

NormalArg.one(1) == .one(1) //Well...? 
NormalArg.one(2) == .one(1) //Well...? 
NormalArg.one(1) == .two //Well...? 

हो सकता है कि यह यह स्पष्ट क्यों इस बॉक्स से बाहर काम नहीं कर सकता है: चलो इस उदाहरण देखते हैं आपके द्वारा अपने enum में प्रोटोकॉल:

enum NormalArg: Equatable { 
    case one(Int) 
    case two 

    static func ==(lhs: NormalArg, rhs: NormalArg) -> Bool { 
     switch (lhs, rhs) { 
     case (let .one(a1), let .one(a2)): 
      return a1 == a2 
     case (.two,.two): 
      return true 
     default: 
      return false 
     } 
    } 
} 
+0

मुझे नहीं पता था कि मैं एक कथन पर 'केस' कीवर्ड जोड़ सकता हूं। –

+1

ओह क्षमा करें, मैंने आपको गलत समझा होगा। मुद्दा यह है कि स्विफ्ट को यह नहीं पता कि डिफ़ॉल्ट रूप से आपके enum को कैसे समझाया जाए यदि यह मूल्यों से जुड़ा हुआ है (जो कच्चे मान में है)। यदि आपके enum में संबंधित मान नहीं हैं या यदि उसके पास कच्चे-मूल्य का प्रकार है, तो आपको मानक लाइब्रेरी (RawRepresentable प्रोटोकॉल I अनुमान से) द्वारा समीकरण प्राप्त होता है। आप निश्चित रूप से जानते हैं कि आप संबंधित मूल्यों को कच्चे प्रकार के साथ मिश्रित नहीं कर सकते हैं और यही कारण है कि आप अपने प्रोटोकॉल पर समेकित लागू किए बिना ".one (Int) == .two" की तुलना नहीं कर सकते। – xxtesaxx

3

उत्तर समतुल्य प्रोटोकॉल है।

अब देखते हैं कि यह कैसे काम करता है। हम enum यह असफल हो जायेगी पर equatable ऑपरेटर == जांच

enum Barcode { 
    case upca(Int, Int) 
    case qrCode(String) 
    case none 
} 

:

उदाहरण के लिए इस enum पर विचार करें।

// Error: binary operator '==' cannot be applied to two Barcode operands 
Barcode.qrCode("code") == Barcode.qrCode("code") 

इक्टेबल प्रोटोकॉल का उपयोग करके इसे कैसे ठीक किया जाए?

extension Barcode: Equatable { 
} 

func ==(lhs: Barcode, rhs: Barcode) -> Bool { 
    switch (lhs, rhs) { 
    case (let .upca(codeA1, codeB1), let .upca(codeA2, codeB2)): 
     return codeA1 == codeA2 && codeB1 == codeB2 

    case (let .qrCode(code1), let .qrCode(code2)): 
     return code1 == code2 

    case (.None, .None): 
     return true 

    default: 
     return false 
    } 
} 

Barcode.qrCode("code") == Barcode.qrCode("code") // true 
Barcode.upca(1234, 1234) == Barcode.upca(4567, 7890) // false 
Barcode.none == Barcode.none // true 
+0

यह एक अच्छा फिक्स है, लेकिन मैं xxtesaxx के उत्तर के साथ जाने के बाद यह आसान हूं। –

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