स्विफ्ट - वर्ग विधि जिसे उपवर्ग द्वारा अधिलेखित किया जाना चाहिए


91

क्या स्विफ्ट में एक "शुद्ध आभासी फ़ंक्शन" बनाने का एक मानक तरीका है, अर्थात। एक जिसे प्रत्येक उपवर्ग द्वारा अधिग्रहित किया जाना चाहिए, और जो, यदि नहीं है, तो संकलन समय त्रुटि का कारण बनता है?


आप इसे सुपर क्लास में लागू कर सकते हैं और एक जोर दे सकते हैं। मैंने इसे ओब्ज-सी, जावा और पायथन में इस्तेमाल किया है।
डेविड स्कर्न्डज़

8
@ सायर्रे यह एक रनटाइम का कारण बनता है, और एक संकलन समय नहीं, त्रुटि
JuJoDi

यह जवाब आपकी भी मदद करेगा। लिंक विवरण यहां दर्ज करें
चमथ जीवन

एक शुद्ध आभासी कार्य protocols ( interfaceजावा में s की तुलना में) द्वारा कार्यान्वित किया जाता है। यदि आपको उन्हें उपयोग करने की आवश्यकता है, जैसे कि अमूर्त विधियों ने इस प्रश्न / उत्तर को देखा है: stackoverflow.com/a/39038828/2435872
jboi

जवाबों:


147

आपके पास दो विकल्प हैं:

1. एक प्रोटोकॉल का उपयोग करें

क्लास के बजाय प्रोटोकॉल के रूप में सुपरक्लास को परिभाषित करें

प्रो : यदि प्रत्येक "उपवर्ग" (वास्तविक उपवर्ग नहीं) के लिए संकलित समय की जाँच आवश्यक विधि लागू करता है

Con : "सुपरक्लास" (प्रोटोकॉल) विधियों या गुणों को लागू नहीं कर सकता है

2. विधि के सुपर संस्करण में जोर दें

उदाहरण:

class SuperClass {
    func someFunc() {
        fatalError("Must Override")
    }
}

class Subclass : SuperClass {
    override func someFunc() {
    }
}

प्रो : सुपरक्लास में तरीकों और गुणों को लागू कर सकते हैं

Con : संकलित समय जाँच नहीं


3
@ जिएविर्थ आपको अभी भी उपकेंद्रों पर एक संकलन समय की जांच नहीं होगी
drewag

5
प्रोटोकॉल विधियों को लागू नहीं कर सकता है, लेकिन आप उन्हें एक्सटेंशन विधियों के बजाय प्रदान कर सकते हैं।
डेविड मोल्स

2
स्विफ्ट 2.0 के रूप में अब प्रोटोकॉल एक्सटेंशन भी हैं :) Apple संदर्भ
एपीमेरा

4
जबकि fatalErrorसंकलन-समय जाँच प्रदान नहीं करता है, यह अच्छा है कि संकलक कम से कम इतना स्मार्ट हो कि आपको निष्पादन पथ को कॉल करने के दौरान विधि के लिए रिटर्न मान प्रदान करने की आवश्यकता न हो fatalError
बगलाफ

3
केस 2: इस तथ्य पर ध्यान दें, यदि आप super.someFunc()ओवरराइड विधि से कॉल करते हैं, तो आपको इस तथ्य के बावजूद त्रुटि मिलती है कि आपने इसे ओवरराइड किया है। आप जानते हैं कि आप इसे कॉल करने के लिए नहीं हैं, लेकिन किसी और को यह जानने की ज़रूरत नहीं है और बस मानक अभ्यास का पालन करें।
जैकब ट्रूहलू

45

निम्नलिखित एक वर्ग से विरासत में मिला है और प्रोटोकॉल के संकलन समय की जांच करने की भी अनुमति देता है :)

protocol ViewControllerProtocol {
    func setupViews()
    func setupConstraints()
}

typealias ViewController = ViewControllerClass & ViewControllerProtocol

class ViewControllerClass : UIViewController {

    override func viewDidLoad() {
        self.setup()
    }

    func setup() {
        guard let controller = self as? ViewController else {
            return
        }

        controller.setupViews()
        controller.setupConstraints()
    }

    //.... and implement methods related to UIViewController at will

}

class SubClass : ViewController {

    //-- in case these aren't here... an error will be presented
    func setupViews() { ... }
    func setupConstraints() { ... }

}

2
बचाव के लिए अच्छा, टाइपियालिया :)
क्रिस एलिंसन

इस एपीआई के उपयोगकर्ताओं को ViewControllerClass से ViewControllerClass से अपने क्लिअर वर्ग को प्राप्त करने से रोकने का कोई तरीका है? यह मेरे लिए बहुत अच्छा समाधान है क्योंकि मैं अब से कुछ साल बाद अपने प्रकार के उपनाम से प्राप्त करूंगा और तब तक यह भूल गया होगा कि कार्यों को क्या करने की आवश्यकता है।
डेविड रेक्टर

@ डेविड रेक्टर, क्या आप अपनी कक्षा को निजी और अपने टाइपियाल को सार्वजनिक कर सकते हैं? मेरे फ़ोन से क्षमा करें संदेश, मैं स्वयं जाँच नहीं कर सकता।
स्कॉट्टीब्लाड्स

1
सही समाधान, इसके लिए धन्यवाद। जैसा कि @DavidRector द्वारा रेखांकित किया गया है, यह बहुत अच्छा होगा अगर इसका समाधान भी हो, ताकि केवल टाइपियालिस सार्वजनिक हो, लेकिन यह दुर्भाग्य से संभव नहीं लगता है।
साइबरडी

35

अमूर्त वर्ग / आभासी कार्यों के लिए कोई समर्थन नहीं है, लेकिन आप शायद ज्यादातर मामलों के लिए एक प्रोटोकॉल का उपयोग कर सकते हैं:

protocol SomeProtocol {
    func someMethod()
}

class SomeClass: SomeProtocol {
    func someMethod() {}
}

अगर SomeClass कुछMethod को लागू नहीं करता है, तो आपको यह संकलन समय त्रुटि मिलेगी:

error: type 'SomeClass' does not conform to protocol 'SomeProtocol'

29
ध्यान दें कि यह केवल उस शीर्ष श्रेणी के लिए काम करता है जो प्रोटोकॉल को लागू करता है। कोई भी उप-वर्ग प्रोटोकॉल की आवश्यकताओं की अनदेखी कर सकता है।
मेमोन्स

2
इसके अलावा, प्रोटोकॉल पर जेनरिक का उपयोग करना समर्थित नहीं है = (
डायल्सन सेल्स

14

एक और वर्कअराउंड, यदि आपके पास बहुत सारे "वर्चुअल" तरीके नहीं हैं, तो उप-वर्ग को "कार्यान्वयन" बेस क्लास कंस्ट्रक्टर में फ़ंक्शन ऑब्जेक्ट के रूप में पास करना है:

class MyVirtual {

    // 'Implementation' provided by subclass
    let fooImpl: (() -> String)

    // Delegates to 'implementation' provided by subclass
    func foo() -> String {
        return fooImpl()
    }

    init(fooImpl: (() -> String)) {
        self.fooImpl = fooImpl
    }
}

class MyImpl: MyVirtual {

    // 'Implementation' for super.foo()
    func myFoo() -> String {
        return "I am foo"
    }

    init() {
        // pass the 'implementation' to the superclass
        super.init(myFoo)
    }
}

1
बहुत उपयोगी नहीं है अगर आपके पास कुछ और आभासी तरीके हैं
बुशरा शाहिद

@ xs2bush यदि आपके तरीकों में से अधिक आभासी हैं, तो संभवत: आप उन्हें प्रोटोकॉल में घोषित करने से बेहतर नहीं हैं, और एक्सटेंशन विधियों के माध्यम से 'गैर-आभासी' प्रदान करते हैं।
डेविड मोल्स

1
बिल्कुल वैसा ही जैसा मैंने किया
बुशरा शाहिद

0

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

मसविदा बनाना

protocol SomeProtocol {
    func someMethod()
}

class SomeClass: SomeProtocol {
    func someMethod() {}
}

अब प्रत्येक उपवर्गों को उस प्रोटोकॉल को लागू करने की आवश्यकता होती है जिसे संकलन समय में जांचा जाता है। यदि SomeClass कुछMethod को लागू नहीं करता है, तो आपको यह संकलन समय त्रुटि मिलेगी:

त्रुटि: टाइप 'SomeClass' प्रोटोकॉल के अनुरूप नहीं है 'SomeProtocol'

नोट: यह केवल प्रोटोकॉल को लागू करने वाले सबसे ऊपरी वर्ग के लिए काम करता है। कोई भी उप-वर्ग प्रोटोकॉल की आवश्यकताओं की अनदेखी कर सकता है। - के रूप में द्वारा टिप्पणी कीmemmons

अभिकथन

class SuperClass {
    func someFunc() {
        fatalError("Must Override")
    }
}

class Subclass : SuperClass {
    override func someFunc() {
    }
}

हालांकि, अभिकथन केवल रनटाइम में काम करेगा।


-2

IOS विकास के लिए नया होने के नाते, जब यह लागू किया गया था, तो मुझे पूरी तरह से यकीन नहीं है, लेकिन दोनों दुनिया के सर्वश्रेष्ठ पाने का एक तरीका प्रोटोकॉल के लिए एक विस्तार को लागू करना है:

protocol ThingsToDo {
    func doThingOne()
}

extension ThingsToDo {
    func doThingTwo() { /* Define code here */}
}

class Person: ThingsToDo {
    func doThingOne() {
        // Already defined in extension
        doThingTwo()
        // Rest of code
    }
}

विस्तार वह है जो आपको फ़ंक्शन के लिए डिफ़ॉल्ट मान रखने की अनुमति देता है जबकि नियमित प्रोटोकॉल में फ़ंक्शन अभी भी परिभाषित नहीं होने पर एक संकलन समय त्रुटि प्रदान करता है


अमूर्त कार्य डिफ़ॉल्ट कार्यान्वयन के विपरीत हैं
हॉगडॉटम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.