स्विफ्ट भाषा में सार कार्य


127

मैं तेज भाषा में सार फ़ंक्शन बनाना चाहता हूं। क्या यह संभव है?

class BaseClass {
    func abstractFunction() {
        // How do I force this function to be overridden?
    }
}

class SubClass : BaseClass {
    override func abstractFunction() {
        // Override
    }
}

यह आपके अन्य प्रश्न के बहुत करीब है, लेकिन यहाँ उत्तर थोड़ा बेहतर लगता है।
डेविड बेरी

प्रश्न समान हैं लेकिन समाधान बहुत अलग हैं क्योंकि एक सार वर्ग में एक सार फ़ंक्शन की तुलना में अलग-अलग उपयोग के मामले हैं।
केव

हां, मैंने या तो बंद करने के लिए मतदान क्यों नहीं किया, लेकिन उत्तर "आप नहीं कर सकते" से परे उपयोगी नहीं होंगे यहां आपको सबसे अच्छा उपलब्ध उत्तर मिला :)
डेविड बेरी

जवाबों:


198

स्विफ्ट में ऑब्जेक्टिव की कोई अवधारणा नहीं है (जैसे ऑब्जेक्टिव-सी) लेकिन आप ऐसा कर सकते हैं:

class BaseClass {
    func abstractFunction() {
        preconditionFailure("This method must be overridden") 
    } 
}

class SubClass : BaseClass {
     override func abstractFunction() {
         // Override
     } 
}

13
वैकल्पिक रूप से आप उपयोग कर सकते हैं assert(false, "This method must be overriden by the subclass")
एरिक

20
याfatalError("This method must be overridden")
नथन

5
जब किसी विधि का रिटर्न प्रकार होता है, तो अभिकथन को रिटर्न स्टेटमेंट की आवश्यकता होगी। मुझे लगता है कि fatalError () इस एक कारण के लिए बेहतर है
एंड्रे फ्रेटेली

6
इसके अलावा preconditionFailure("Bla bla bla")स्विफ्ट में है जो रिलीज बिल्ड में निष्पादित करेगा और रिटर्न स्टेटमेंट की आवश्यकता को भी समाप्त करेगा। संपादित करें: बस यह पता चला है कि यह विधि मूल रूप से बराबर है, fatalError()लेकिन यह अधिक उचित तरीका है (बेहतर प्रलेखन, स्विफ्ट में पेश किया गया precondition(), assert()और assertionFailure(), यहाँ पढ़ें )
केमेट्रिक्सम

2
क्या होगा अगर फ़ंक्शन का रिटर्न प्रकार है?
लवमेव

36

आप जो चाहते हैं वह बेस क्लास नहीं है, बल्कि एक प्रोटोकॉल है।

protocol MyProtocol {
    func abstractFunction()
}

class MyClass : MyProtocol {
    func abstractFunction() {
    }
}

यदि आप अपनी कक्षा में अमूर्त आपूर्ति नहीं करते हैं तो यह एक त्रुटि है।

यदि आपको अभी भी अन्य व्यवहार के लिए बेसकेल्स की आवश्यकता है, तो आप यह कर सकते हैं:

class MyClass : BaseClass, MyProtocol {
    func abstractFunction() {
    }
}

23
यह काफी काम नहीं करता है। यदि BaseClass उन खाली फ़ंक्शन को कॉल करना चाहता है, तो उसे भी प्रोटोकॉल लागू करना होगा, और फिर फ़ंक्शन को लागू करना होगा। इसके अलावा उपवर्ग अभी भी संकलन समय पर कार्यों को लागू करने के लिए मजबूर नहीं है, और आपने प्रोटोकॉल को लागू करने के लिए मजबूर नहीं किया है।
बांदीजापीसा

5
यह मेरी बात है .... BaseClass का प्रोटोकॉल से कोई लेना-देना नहीं है, और एक अमूर्त वर्ग की तरह काम करने के लिए इसके साथ कुछ करना चाहिए। यह स्पष्ट करने के लिए कि मैंने क्या लिखा है "अगर बेसक्लास उन खाली कार्यों को कॉल करना चाहता है, तो उसे प्रोटोकॉल को भी लागू करना होगा जो आपको कार्यों को लागू करने के लिए मजबूर करेगा - जिसके बाद संकलन समय पर कार्यों को लागू करने के लिए मजबूर नहीं होने के लिए उपवर्ग की ओर जाता है, क्योंकि बेसक्लास ने पहले ही कर दिया है "।
बांदीजापीसा

4
यह वास्तव में इस बात पर निर्भर करता है कि आप "अमूर्त" को कैसे परिभाषित करते हैं। एक सार फ़ंक्शन का पूरा बिंदु यह है कि आप इसे एक वर्ग पर रख सकते हैं जो सामान्य वर्ग की चीजें कर सकते हैं। उदाहरण के लिए, मैं यही चाहता हूं, क्योंकि मुझे एक स्थिर सदस्य को परिभाषित करने की आवश्यकता है जो आप प्रोटोकॉल के साथ नहीं कर सकते। इसलिए मेरे लिए यह देखना मुश्किल है कि यह एक सार फ़ंक्शन के उपयोगी बिंदु से मिलता है।
पक्की

3
मुझे लगता है कि ऊपर उल्लिखित टिप्पणियों के साथ चिंता यह है कि यह लिस्कोव प्रतिस्थापन सिद्धांत के अनुरूप नहीं है जो बताता है कि "किसी कार्यक्रम में वस्तुओं को उस कार्यक्रम की शुद्धता में बदलाव किए बिना उनके उपप्रकारों के उदाहरणों के साथ बदली जा सकती है।" यह माना जाता है कि यह एक अमूर्त प्रकार है। यह फैक्ट्री मेथड पैटर्न के मामले में विशेष रूप से महत्वपूर्ण है जहां बेस क्लास उप क्लास से उत्पन्न होने वाले गुणों को बनाने और संग्रहीत करने के लिए जिम्मेदार है।
डेविड जेम्स

2
एक सार आधार वर्ग और एक प्रोटोकॉल एक ही बात नहीं है।
शोएरॉब

29

मैं एक प्लेटफ़ॉर्म से कोड की एक उचित मात्रा को पोर्ट करता हूं जो एब्सट्रैक्ट बेस क्लास को स्विफ्ट को सपोर्ट करता है और इसमें बहुत रन करता है। यदि आप वास्तव में चाहते हैं कि एक सार आधार वर्ग की कार्यक्षमता है, तो इसका मतलब है कि यह वर्ग साझा आधारित वर्ग कार्यक्षमता के कार्यान्वयन के रूप में दोनों कार्य करता है (अन्यथा यह सिर्फ एक इंटरफ़ेस / प्रोटोकॉल होगा) और यह उन तरीकों को परिभाषित करता है जिन्हें लागू करना चाहिए व्युत्पन्न वर्ग।

स्विफ्ट में ऐसा करने के लिए, आपको एक प्रोटोकॉल और बेस क्लास की आवश्यकता होगी।

protocol Thing
{
    func sharedFunction()
    func abstractFunction()
}

class BaseThing
{
    func sharedFunction()
    {
        println("All classes share this implementation")
    }
}

ध्यान दें कि बेस क्लास साझा विधि को लागू करता है, लेकिन प्रोटोकॉल को लागू नहीं करता है (क्योंकि यह सभी तरीकों को लागू नहीं करता है)।

फिर व्युत्पन्न वर्ग में:

class DerivedThing : BaseThing, Thing 
{
    func abstractFunction() 
    {
        println("Derived classes implement this");
    }
}

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

इस पद्धति का एकमात्र वास्तविक पहलू यह है कि चूंकि बेस क्लास प्रोटोकॉल को लागू नहीं करता है, अगर आपके पास बेस क्लास विधि है, जिसे प्रोटोकॉल प्रॉपर्टी / विधि तक पहुंच की आवश्यकता है, तो आपको उस व्युत्पन्न वर्ग में ओवरराइड करना होगा, और वहां से कॉल करना होगा। बेस क्लास (सुपर के माध्यम से) गुजर रहा है selfताकि बेस क्लास में प्रोटोकॉल का एक उदाहरण है जिसके साथ अपना काम करना है।

उदाहरण के लिए, यह बताता है कि साझाकरण को अमूर्त कॉल करने की आवश्यकता है। प्रोटोकॉल समान रहेगा, और कक्षाएं अब इस तरह दिखेंगी:

class BaseThing
{
    func sharedFunction(thing: Thing)
    {
        println("All classes share this implementation")
        thing.abstractFunction()
    }
}

class DerivedThing : BaseThing, Thing 
{
    func sharedFunction()
    {
        super.sharedFunction(self)
    }

    func abstractFunction() 
    {
        println("Derived classes implement this");
    }
}

अब व्युत्पन्न वर्ग से साझाकरण प्रोटोकॉल के उस हिस्से को संतुष्ट कर रहा है, लेकिन व्युत्पन्न वर्ग अभी भी आधार वर्ग तर्क को यथोचित रूप से साझा करने में सक्षम है।


4
"बेस क्लास प्रोटोकॉल लागू नहीं करता है" पर बहुत अच्छी समझ और अच्छी गहराई ... जो एक अमूर्त वर्ग के बिंदु की तरह है। मैं चकित हूं कि यह मूल OO सुविधा गायब है, लेकिन फिर, मुझे जावा पर उठाया गया था।
दान रोसेनस्टार्क

2
फिर भी कार्यान्वयन टेम्पलेट फ़ंक्शन पद्धति को मूल रूप से कार्यान्वित करने की अनुमति नहीं देता है जहां टेम्पलेट विधि उपखंडों में लागू सार विधियों की एक विस्तृत संख्या को बुलाती है। इस मामले में आपको उन दोनों को सुपर क्लास में सामान्य तरीकों के रूप में, प्रोटोकॉल में विधियों और फिर उपवर्ग में कार्यान्वयन के रूप में लिखना चाहिए। व्यवहार में आपको तीन बार एक ही सामान लिखना होगा और केवल ओवरराइड चेक पर भरोसा करना होगा ताकि कोई भी विनाशकारी गलत वर्तनी न हो! मुझे वास्तव में अब उम्मीद है कि स्विफ्ट डेवलपर्स के लिए खुला है, पूर्ण-सार सार फ़ंक्शन का परिचय होगा।
फैब्रीज़ियो बार्टोलोमुची

1
इतना समय, और कोड "संरक्षित" कीवर्ड शुरू करके बचाया जा सकता है।
शोएरॉब

23

यह एक "आधिकारिक" तरीका प्रतीत होता है कि कैसे ऐप्प UIKit में सार विधियों को संभाल रहा है। एक नज़र डालें UITableViewControllerऔर जिस तरह से यह काम कर रहा है UITableViewDelegate। आपके द्वारा की जाने वाली सबसे पहली चीजों में से एक है, एक पंक्ति जोड़ना:delegate = self :। खैर, यह बिल्कुल चाल है।

1. एक प्रोटोकॉल में अमूर्त विधि रखो
protocol AbstractMethodsForClassX {
    func abstractMethod() -> String
}
2. अपना आधार वर्ग लिखें
/// It takes an implementation of the protocol as property (same like the delegate in UITableViewController does)
/// And does not implement the protocol as it does not implement the abstract methods. It has the abstract methods available in the `delegate`
class BaseClassX {
    var delegate: AbstractMethodsForClassX!

    func doSomethingWithAbstractMethod() -> String {
        return delegate.abstractMethod() + " - And I believe it"
    }
}
3. उपवर्ग (तों) लिखें।
/// First and only additional thing you have to do, you must set the "delegate" property
class ClassX: BaseClassX, AbstractMethodsForClassX {
    override init() {
        super.init()
        delegate = self
    }

    func abstractMethod() -> String {return "Yes, this works!"}
}
यहाँ है, आप कैसे है कि सभी का उपयोग करें
let x = ClassX()
x.doSomethingWithAbstractMethod()

आउटपुट देखने के लिए खेल के मैदान के साथ जांचें।

कुछ रिमार्क्स

  • पहले, बहुत सारे जवाब पहले ही दिए गए थे। मुझे उम्मीद है कि किसी को इस एक के लिए नीचे सभी तरह पाता है
  • सवाल वास्तव में था, एक पैटर्न को खोजने के लिए जो लागू होता है:
    • एक वर्ग एक विधि कहता है, जिसे उसके व्युत्पन्न उपवर्गों (ओवरराइड) में से एक में लागू किया जाना है
    • सबसे अच्छा मामले में, यदि विधि उपवर्ग में ओवरराइड नहीं है, तो संकलन समय के दौरान एक त्रुटि प्राप्त करें
  • अमूर्त तरीकों के बारे में बात यह है, कि वे एक इंटरफ़ेस परिभाषा का एक मिश्रण हैं और बेस क्लास में वास्तविक कार्यान्वयन का हिस्सा हैं। एक ही समय में दोनों। जैसा कि स्विफ्ट बहुत नया और बहुत साफ परिभाषित है, इसमें ऐसी कोई सहूलियत नहीं है लेकिन "अशुद्ध" अवधारणाएं (अभी तक) हैं।
  • मेरे लिए (एक गरीब पुराने जावा पुरुष), यह समस्या समय-समय पर विकसित होती है। मैंने इस पोस्ट में सभी उत्तरों को पढ़ा है और इस बार मुझे लगता है कि मुझे एक पैटर्न मिला है, जो व्यवहार्य लगता है - कम से कम मेरे लिए।
  • अद्यतन : ऐसा लगता है कि Apple में UIKit कार्यान्वयनकर्ता समान पैटर्न का उपयोग करते हैं। UITableViewControllerकार्यान्वयन UITableViewDelegateलेकिन अभी भी delegateसंपत्ति को स्पष्ट रूप से स्थापित करके प्रतिनिधि के रूप में पंजीकृत होने की आवश्यकता है ।
  • यह सब Xcode 7.3.1 के प्लेग्राउंड पर परीक्षण किया गया है

शायद सही नहीं है, क्योंकि मुझे अन्य कक्षाओं से कक्षा के इंटरफ़ेस को छिपाने में समस्या है, लेकिन स्विफ्ट में क्लासिक फैक्ट्री विधि को लागू करने के लिए मुझे पर्याप्त आवश्यकता है।
टोमाज़ Nazarenko

हममम। मुझे इस उत्तर की झलक बहुत अधिक पसंद है, लेकिन मुझे यकीन नहीं है कि यह उपयुक्त है। यानी, मेरे पास एक ViewController है जो विभिन्न प्रकार की वस्तुओं के एक मुट्ठी भर के लिए जानकारी प्रदर्शित कर सकता है, लेकिन उस जानकारी को प्रदर्शित करने का उद्देश्य सभी समान तरीकों के साथ है, लेकिन ऑब्जेक्ट के आधार पर अलग-अलग जानकारी खींचना और एक साथ रखना । इसलिए, मेरे पास इस VC के लिए एक पैरेंट डेलिगेट वर्ग है, और प्रत्येक प्रकार की ऑब्जेक्ट के लिए उस डेलीगेट का एक उपवर्ग है। मैं पास की गई वस्तु के आधार पर एक प्रतिनिधि को तत्काल भेज देता हूं। एक उदाहरण में, प्रत्येक वस्तु में कुछ प्रासंगिक टिप्पणियां संग्रहीत होती हैं।
जेक टी।

इसलिए मेरे पास getCommentsपैरेंट डेलिगेट पर एक तरीका है। कुछ प्रकार के टिप्पणी प्रकार होते हैं, और मैं प्रत्येक वस्तु के लिए प्रासंगिक चाहता हूं। इसलिए, मैं चाहता हूं कि जब मैं delegate.getComments()उस विधि को ओवरराइड नहीं करता तो उपवर्गों को संकलित नहीं करना चाहिए। वीसी को पता है कि उसके पास एक ParentDelegateऑब्जेक्ट है delegate, या BaseClassXआपके उदाहरण में, लेकिन BaseClassXअमूर्त विधि नहीं है। मुझे वीसी की आवश्यकता होगी, विशेष रूप से यह जानने के लिए कि यह उपयोग कर रहा है SubclassedDelegate
जेक टी।

मुझे उम्मीद है कि मैं आपको सही समझूंगा। यदि नहीं, तो क्या आप एक नया प्रश्न पूछना चाहते हैं, जहां आप कुछ कोड जोड़ सकते हैं? मुझे लगता है कि आपको केवल if doSomethingWithAbstractMethod 'जाँच में एक स्टेटमेंट रखना होगा, अगर प्रतिनिधि सेट है या नहीं।
जौबी

यह उल्लेख के लायक है कि प्रतिनिधि को स्वयं असाइन करना एक चक्र बनाए रखता है। शायद इसे कमजोर घोषित करना बेहतर है (जो आमतौर पर प्रतिनिधियों के लिए एक अच्छा विचार है)
एनरिकोज़ा

7

ऐसा करने का एक तरीका आधार वर्ग में परिभाषित वैकल्पिक बंद का उपयोग करना है, और बच्चे इसे लागू करने के लिए चुन सकते हैं या नहीं।

class BaseClass {
    var abstractClosure?:(()->())?
    func someFunc()
    {
        if let abstractClosure=abstractClosure
        {
            abstractClosure()
        }
    } 
}

class SubClass : BaseClass {
    init()
    {
        super.init()
        abstractClosure={ ..... }
    }
}

इस दृष्टिकोण के बारे में मुझे जो पसंद है वह यह है कि मुझे वंशानुक्रम में एक प्रोटोकॉल को लागू करने के लिए याद नहीं रखना है। मेरे पास अपने ViewControllers के लिए एक आधार वर्ग है, और यह है कि मैं ViewController विशिष्ट, वैकल्पिक कार्यक्षमता (जैसे ऐप सक्रिय हो गया, आदि) को लागू करता है जो आधार वर्ग की कार्यक्षमता द्वारा लागू हो सकता है।
प्रोग्राममेयियर

6

खैर, मुझे पता है कि मुझे खेल में देर हो चुकी है और हो सकता है कि मैं उन बदलावों का फायदा उठाऊं जो हो चुके हैं। उसके लिए माफ़ करना।

किसी भी मामले में, मैं अपने उत्तर में योगदान देना चाहूंगा, क्योंकि मुझे परीक्षण करना पसंद है और इसके साथ समाधान fatalError()है, AFAIK, परीक्षण योग्य नहीं है और अपवाद वाले लोग परीक्षण के लिए बहुत कठिन हैं।

मैं सुझाव दूंगा कि अधिक स्वाइप अप्रोच का उपयोग करें । आपका लक्ष्य एक अमूर्तता को परिभाषित करना है जिसमें कुछ सामान्य विवरण हैं, लेकिन यह पूरी तरह से परिभाषित नहीं है, अर्थात सार विधि (s)। एक प्रोटोकॉल का उपयोग करें जो अमूर्त में सभी अपेक्षित तरीकों को परिभाषित करता है, दोनों को परिभाषित किया गया है, और वे भी जो नहीं हैं। फिर एक प्रोटोकॉल एक्सटेंशन बनाएं जो आपके मामले में परिभाषित तरीकों को लागू करता है। अंत में, किसी भी व्युत्पन्न वर्ग को प्रोटोकॉल लागू करना चाहिए, जिसका अर्थ है सभी विधियाँ, लेकिन जो प्रोटोकॉल विस्तार का हिस्सा हैं, उनका कार्यान्वयन पहले से ही है।

एक ठोस कार्य के साथ अपने उदाहरण का विस्तार:

protocol BaseAbstraction {
    func abstractFunction() {
        // How do I force this function to be overridden?
    }
}

extension BaseAbstraction {
    func definedFunction() {
        print("Hello")
}

class SubClass : BaseAbstraction {
    func abstractFunction() {
        // No need to "Override". Just implement.
    }
}

ध्यान दें कि ऐसा करने से, कंपाइलर फिर से आपका दोस्त है। यदि विधि "ओवरराइड" नहीं है, तो आपको संकलन समय पर एक त्रुटि मिलेगी, बजाय इसके कि आप उन लोगों के साथ मिलेंगे fatalError()या जो अपवाद हैं जो कि रन टाइम पर होते हैं।


1
सबसे अच्छा जवाब Imo।
Apfelsaft

1
अच्छा जवाब है, लेकिन आपका आधार अमूर्त संपत्तियों को संचय करने में सक्षम नहीं है, हालांकि
joehinkle11

5

मैं समझता हूं कि अब आप क्या कर रहे हैं, मुझे लगता है कि आप एक प्रोटोकॉल का उपयोग करके बेहतर होंगे

protocol BaseProtocol {
    func abstractFunction()
}

फिर, आप सिर्फ प्रोटोकॉल के अनुरूप हैं:

class SubClass : BaseProtocol {

    func abstractFunction() {
        // Override
        println("Override")
    }
}

यदि आप वर्ग भी एक उपवर्ग है, तो प्रोटोकॉल सुपरक्लास का अनुसरण करते हैं:

class SubClass: SuperClass, ProtocolOne, ProtocolTwo {}

3

assertअमूर्त विधियों को लागू करने के लिए कीवर्ड का उपयोग करना :

class Abstract
{
    func doWork()
    {
        assert(false, "This method must be overriden by the subclass")
    }
}

class Concrete : Abstract
{
    override func doWork()
    {
        println("Did some work!")
    }
}

let abstract = Abstract()
let concrete = Concrete()

abstract.doWork()    // fails
concrete.doWork()    // OK

हालांकि, जैसा कि स्टीव वाडिकोर ने उल्लेख किया है कि आप शायद protocolइसके बजाय चाहते हैं ।


अमूर्त तरीकों का लाभ यह है कि चेक संकलन समय पर किए जाते हैं।
फेब्रीज़ियो बार्टोलोमुची

मुखर का उपयोग न करें, क्योंकि संग्रह करने पर, यू 'त्रुटि वापस करने के लिए अपेक्षित फ़ंक्शन में अनुपलब्धता' प्राप्त करेगा। FatalError का उपयोग करें ("इस विधि को उपवर्ग द्वारा ओवरराइड किया जाना चाहिए")
Zaporozhchenko ऑलेक्ज़ेंडर

2

मैं प्रश्न को समझता हूं और उसी समाधान की तलाश में था। प्रोटोकॉल एब्सट्रैक्ट के तरीकों के समान नहीं हैं।

एक प्रोटोकॉल में आपको यह निर्दिष्ट करने की आवश्यकता है कि आपका वर्ग इस तरह के प्रोटोकॉल के अनुरूप है, एक अमूर्त विधि का मतलब है कि आपको ऐसी विधि को ओवरराइड करना होगा।

दूसरे शब्दों में, प्रोटोकॉल एक प्रकार के वैकल्पिक हैं, आपको बेस क्लास और प्रोटोकॉल निर्दिष्ट करने की आवश्यकता है, यदि आप प्रोटोकॉल निर्दिष्ट नहीं करते हैं, तो आपको ऐसे तरीकों को ओवरराइड करने की आवश्यकता नहीं है।

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

मुझे उसी व्यवहार की आवश्यकता है, यही कारण है कि मैं एक समाधान की तलाश में था। मुझे लगता है कि स्विफ्ट ऐसी सुविधा को याद कर रही है।


1

इस मुद्दे का एक और विकल्प है, हालांकि @ जूमर्ड के प्रस्ताव की तुलना में अभी भी एक नकारात्मक पहलू है; इसके लिए रिटर्न स्टेटमेंट की जरूरत होती है। हालाँकि मुझे इसकी आवश्यकता की बात याद आती है, क्योंकि इसमें सीधे तौर पर एक अपवाद को शामिल किया गया है:

class AbstractMethodException : NSException {

    init() {
        super.init(
            name: "Called an abstract method",
            reason: "All abstract methods must be overriden by subclasses",
            userInfo: nil
        );
    }
}

और तब:

class BaseClass {
    func abstractFunction() {
        AbstractMethodException.raise();
    }
}

उसके बाद जो भी आता है, वह अप्राप्य है, इसलिए मैं यह नहीं देखता कि वापसी को मजबूर क्यों किया जाए।


क्या आपका मतलब है AbstractMethodException().raise()?
जोशकोड्स

शायद ... शायद। मैं अभी परीक्षण नहीं कर सकता, लेकिन अगर यह उस तरह से काम करता है, तो हां
एंड्रे फ्रेटेली

1

मुझे नहीं पता कि यह उपयोगी होने जा रहा है, लेकिन स्प्रीकिट गेम बनाने की कोशिश करते समय मुझे सार पद्धति के साथ एक समान मुद्दा था। मैं जो चाहता था वह एक अमूर्त पशु वर्ग है जिसमें कदम (), रन () आदि जैसे तरीके हैं, लेकिन स्प्रिट नाम (और अन्य कार्यक्षमता) कक्षा के बच्चों द्वारा प्रदान किए जाने चाहिए। इसलिए मैंने कुछ इस तरह किया (स्विफ्ट 2 के लिए परीक्षण)

import SpriteKit

// --- Functions that must be implemented by child of Animal
public protocol InheritedAnimal
{
    func walkSpriteNames() -> [String]
    func runSpriteNames() -> [String]
}


// --- Abstract animal
public class Animal: SKNode
{
    private let inheritedAnimal: InheritedAnimal

    public init(inheritedAnimal: InheritedAnimal)
    {
        self.inheritedAnimal = inheritedAnimal
        super.init()
    }

    public required init?(coder aDecoder: NSCoder)
    {
        fatalError("NSCoding not supported")
    }

    public func walk()
    {
        let sprites = inheritedAnimal.walkSpriteNames()
        // create animation with walking sprites...
    }

    public func run()
    {
        let sprites = inheritedAnimal.runSpriteNames()
        // create animation with running sprites
    }
}


// --- Sheep
public class SheepAnimal: Animal
{
    public required init?(coder aDecoder: NSCoder)
    {
        fatalError("NSCoding not supported")
    }

    public required init()
    {
        super.init(inheritedAnimal: InheritedAnimalImpl())
    }

    private class InheritedAnimalImpl: InheritedAnimal
    {
        init() {}

        func walkSpriteNames() -> [String]
        {
            return ["sheep_step_01", "sheep_step_02", "sheep_step_03", "sheep_step_04"]
        }

        func runSpriteNames() -> [String]
        {
            return ["sheep_run_01", "sheep_run_02"]
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.