2015-06-01 6 views
7

स्विफ्ट में कोई सार वर्ग और विधियां नहीं हैं। इसके बजाय, यह प्रोटोकॉल प्रदान करता है।स्विफ्ट - मिश्रण अमूर्त और ठोस तरीके

यह ठीक है जब आपकी कक्षाएं पूरी तरह से सार या पूरी तरह से ठोस होती हैं।

लेकिन एक अमूर्त वर्ग को लागू करने के लिए सबसे अच्छा 'स्विफ्ट' तरीका क्या है जिसमें ठोस तरीके भी हैं?

छद्म कोड उदाहरण:

class Animal { 
    abstract makeSound() 
    abstract eyeCount() 
} 

class Mammal : Animal { 
    override eyeCount { return 2 } // Let's assume all mammals have hard-coded 2 eyes... 

class Cat : Mammal { 
    override makeSound { print "Meow!" } 
} 

class Dog : Mammal { 
    override makeSound { print "Woof!" } 
} 

स्तनपायी में, मैं ठोस विधि eyeCount() लागू करने के लिए है क्योंकि सभी स्तनधारियों 2 हार्ड-कोडेड आँखें (माना जाता है कि है) चाहते हैं और मैं फिर से नहीं करना चाहते इसे कुत्ते और बिल्ली में लागू करें। हालांकि, makeSound() केवल कुत्ते और बिल्ली के लिए लागू किया जाना चाहिए क्योंकि स्तनधारियों की अलग-अलग आवाजें होती हैं।

स्विफ्ट में आप इसे कैसे कार्यान्वित करेंगे? धन्यवाद!

उत्तर

6

मैं इसे इस तरह लागू करना होगा::

+0

मुझे वास्तव में उन चीज़ों में परेशानी है जो केवल रनटाइम के दौरान गलत होने की घोषणा करते हैं। यह कोड अविश्वसनीय बनाता है। एक कार्यान्वयन के लिए @pommes उत्तर या यह जांचें, जो संकलन समय के दौरान जांचता है http://stackoverflow.com/a/39038828/2435872 – jboi

0

ऐसा करने के लिए एक आम विधि एक अमूर्त वर्ग है जिसमें ठोस तरीके हैं। सभी वर्ग कंक्रीट विधियों के साथ-साथ अमूर्त तरीकों के उत्तराधिकारी के लिए इस अमूर्त वर्ग को उपclass कर सकते हैं।

UIGuestureRecognizer और UIGuestureRecognizerSubclass इसका एक बहुत अच्छा उदाहरण है। चूंकि यह उप-वर्गीकरण के लिए है, इस अमूर्त वर्ग में आपके लिए लागू करने के लिए कई आंतरिक ठोस विधियों के साथ-साथ उप-वर्गीकरण सार तत्व भी शामिल हैं।

यह कई स्विफ्ट और उद्देश्य-सी परियोजनाओं के लिए एक आम पैटर्न है।

protocol Animal { 
    var eyeCount: Int { get } 
    func makeSound() 
} 

// Note - `Mammal` doesn't conform to `Animal`. 
class Mammal { 
    let eyeCount = 2 
} 

// Only `Cat` and `Dog` conform to `Animal`, so only they need to implement `makeSound`. 
class Dog: Mammal, Animal { 
    func makeSound() { 
     println("Woof") 
    } 
} 

class Cat: Mammal, Animal { 
    func makeSound() { 
     println("Meow") 
    } 
} 
+0

मैंने स्विफ्ट में कुछ ऐसा करने की कोशिश की। हालांकि, मुझे "My UIGestureRecgonizerSubclass" पर एक कंपाइलर त्रुटि मिली क्योंकि उसने "My UIGestureRecognizer" प्रोटोकॉल में घोषित (आवश्यक) विधियों को लागू नहीं किया था। –

+1

यदि आप प्रोटोकॉल का पालन करने का निर्णय लेते हैं तो आपको आवश्यक विधियों को लागू करना होगा जब तक वे विधियां '@ वैकल्पिक' न हों। – Schemetrical

+0

आप सही हैं। हालांकि, मैं ठोस 'पत्ते' वर्गों से बचना चाहता हूं जहां प्रोटोकॉल से वैकल्पिक तरीके ** ** लागू नहीं किए गए हैं। इससे 'प्रतिक्रिया करने के लिए चयनकर्ता' कॉल का कारण बन जाएगा - मेरी विनम्र राय में एक कोड डरावनी। –

0

एक ही रास्ता के रूप में Abstract functions in Swift Language में @BobDickinson ने सुझाव दिया कि आप ऐसा कर सकता है, है, तो निम्न है

class AbstractAnimal 
{ 
    // Fully abstract method 
    func methodThatReturnsSomething() -> String { 
     fatalError("methodThatReturnsSomething() is abstract and must be overriden!"); 
    } 

    func eyeCount() -> Int { 
     return 2; 
    } 
} 

fatalError शिकायत से Xcode रोकता है अमूर्त विधि methodThatReturnsSomething() वास्तव में कुछ भी वापस नहीं करता है। जाँच हो रही है सार तरीकों संकलन समय पर उपवर्गों में लागू कर रहे हैं:

+0

यह एक अच्छा समाधान है। हालांकि, मैं अलग-अलग स्तनधारी और पशु को विरासत में लाने से बचूंगा।एक स्तनधारी एक पशु है, और इसलिए स्तनधारियों के हर उप-वर्ग को भी पशु को लागू करना चाहिए। –

+0

इसके अलावा, अमूर्तता के लिए, मान लें कि ** eyeCount ** एक गेटटर के साथ एक संपत्ति के बजाय एक समारोह है। यह एक उदाहरण की एक गरीब पसंद थी। –

3

आप सार कक्षाएं के साथ के रूप में ठीक उसी व्यवहार पाने के लिए प्रोटोकॉल एक्सटेंशन उपयोग कर सकते हैं।

protocol Entity { 
    // MARK: - Abstract methods 
    func filename() -> String 

    // MARK: - Traits 
    func saveData(data: NSArray) 
} 

extension Entity { 
    func saveData(data: NSArray) { 
     // Do something and call: 
     let filename = filename() 
    } 
} 

अब आप एक उपवर्ग पर Entity प्रोटोकॉल को लागू कर सकते हैं और संकलक filename() लागू करने के लिए, जबकि saveData() पद्धति पहले से ही लागू किया गया है आप के लिए बाध्य करेगा।

+1

अच्छा, लेकिन एक अमूर्त वर्ग में मैं चर परिभाषित कर सकता हूं और उन्हें funcs में उपयोग कर सकता हूं। यहां मुझे प्रोटोकॉल को लागू करने वाले प्रत्येक वर्ग में चर घोषित करना होगा और उन्हें एक्सेसर विधियों के माध्यम से एक्सटेंशन से एक्सेस करना होगा, या क्या कोई बेहतर तरीका है? – AmigoNico

+0

एक्सटेंशन संग्रहित गुण नहीं हो सकते हैं, इसलिए यह दृष्टिकोण सीमित है। – Raphael

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