स्विफ्ट में संग्रहीत संपत्ति को ओवरराइड करना


126

मैंने देखा कि संकलक मुझे एक संग्रहीत संपत्ति को किसी अन्य संग्रहीत मान के साथ ओवरराइड नहीं करने देगा (जो कि अजीब लगता है):

class Jedi {
    var lightSaberColor = "Blue"
}


class Sith: Jedi {
    override var lightSaberColor = "Red" // Cannot override with a stored property lightSaberColor
}

हालाँकि, मुझे इसकी गणना संपत्तियों के साथ करने की अनुमति है:

class Jedi {
    let lightSaberColor = "Blue"
}


class Sith: Jedi {
    override var lightSaberColor : String{return "Red"}

}

मुझे इसे दूसरा मूल्य देने की अनुमति क्यों नहीं है?

क्यों एक संग्रहीत संपत्ति के साथ ओवरराइड कर रहा है और एक गणना एक कोषेर के साथ कर रहा है? वे कहाँ सोच रहे थे?


जवाबों:


82

मुझे इसे केवल एक और मूल्य देने की अनुमति क्यों नहीं है?

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

class Jedi {
    // I made lightSaberColor read-only; you can make it writable if you prefer.
    let lightSaberColor : String
    init(_ lsc : String = "Blue") {
        lightSaberColor = lsc;
    }
}

class Sith : Jedi {
    init() {
        super.init("Red")
    }
}

let j1 = Jedi()
let j2 = Sith()

println(j1.lightSaberColor)
println(j2.lightSaberColor)

किसी संपत्ति को ओवरराइड करना एक नया मूल्य देने के समान नहीं है - यह एक वर्ग को एक अलग संपत्ति देने की तरह है। वास्तव में, ऐसा तब होता है जब आप एक गणना की गई संपत्ति को ओवरराइड करते हैं: आधार वर्ग में संपत्ति की गणना करने वाले कोड को उस कोड से बदल दिया जाता है जो व्युत्पन्न वर्ग में उस संपत्ति के लिए ओवरराइड की गणना करता है।

[क्या यह] संग्रहीत वास्तविक संपत्ति को ओवरराइड करने के लिए संभव है, अर्थात lightSaberColorइसमें कुछ अन्य व्यवहार है?

पर्यवेक्षकों के अलावा, संग्रहीत गुणों में व्यवहार नहीं होता है, इसलिए ओवरराइड करने के लिए वास्तव में कुछ भी नहीं है। ऊपर वर्णित तंत्र के माध्यम से संपत्ति को एक अलग मूल्य देना संभव है। यह वही करता है जो प्रश्न में उदाहरण एक अलग वाक्यविन्यास के साथ हासिल करने की कोशिश कर रहा है।


2
@MaxMacLeod पर्यवेक्षकों के अलावा, संग्रहीत संपत्तियों में व्यवहार नहीं होता है, इसलिए ओवरराइड करने के लिए वास्तव में कुछ भी नहीं है। वह एक संग्रहीत संपत्ति को उपवर्ग में एक अलग मूल्य देना चाहता था, लेकिन वह इसे प्राप्त करने के लिए तंत्र के बारे में अनिश्चित था। जवाब बताता है कि स्विफ्ट में यह कैसे किया जा सकता है। मुझे देर से उत्तर के लिए खेद है, ऐसा प्रतीत होता है कि आपकी टिप्पणी डाउनवोट को आकर्षित करने के लिए पर्याप्त भ्रम का कारण बनती है, इसलिए मैंने यह समझाने का फैसला किया कि क्या हो रहा है।
dasblinkenlight

55

मेरे लिए, आपका उदाहरण स्विफ्ट 3.0.1 में काम नहीं करता है।

मैंने इस कोड को खेल के मैदान में दर्ज किया:

class Jedi {
    let lightsaberColor = "Blue"
}

class Sith: Jedi {
    override var lightsaberColor : String {
        return "Red"
    }
}

Xcode में संकलन समय पर त्रुटि फेंकता है:

एक 'var' के गेट के साथ अपरिवर्तनीय 'लेट' प्रॉपर्टी 'LightsaberColor' को ओवरराइड नहीं कर सकते

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

लेकिन अगर आप इसे बदल देते हैं varऔर इसलिए setगणना की गई संपत्ति में जोड़ते हैं, तो आप उसी प्रकार की गणना की गई संपत्ति के साथ संग्रहीत संपत्ति को ओवरराइड कर सकते हैं।

class Jedi {
    var lightsaberColor = "Blue"
}


class Sith: Jedi {
    override var lightsaberColor : String {
        get {
            return "Red"
        }
        set {
            // nothing, because only red is allowed
        }
    }
}

यह संभव है क्योंकि यह संग्रहीत संपत्ति से गणना की गई संपत्ति पर स्विच करने का अर्थ बना सकता है।

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

हालाँकि, आप किसी संग्रहीत संपत्ति के साथ संग्रहीत संपत्ति को ओवरराइड नहीं कर सकते।


मैं यह नहीं कहूंगा कि सीथ जेडी हैं :- पी। इसलिए यह स्पष्ट है कि यह काम नहीं कर सकता है।


18
class SomeClass {
    var hello = "hello"
}
class ChildClass: SomeClass {
    override var hello: String {
        set {
            super.hello = newValue
        }
        get {
            return super.hello
        }    
    }
}

13
हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और उन लोगों को आपके कोड सुझाव के कारणों का पता नहीं चल सकता है।
दिमासन

15

आप शायद संपत्ति के लिए एक और मूल्य का आश्वासन देना चाहते हैं:

class Jedi {
    var lightSaberColor = "Blue"
}


class Sith: Jedi {
    override init() {
        super.init()
        self.lightSaberColor = "Red"
    }
}

9
ऊपर की टिप्पणी के अनुसार भी यही लागू होता है
मैक्स मैकलेड

10

एप्पल के प्रलेखन से स्विफ्ट 4 के लिए :

आप एक अंतर्निहित उदाहरण को ओवरराइड कर सकते हैं या उस संपत्ति के लिए अपने स्वयं के कस्टम गेट्टर और सेटर प्रदान करने के लिए संपत्ति टाइप कर सकते हैं, या अंतर्निहित संपत्ति मूल्य में परिवर्तन होने पर ओवरराइडिंग संपत्ति को देखने के लिए संपत्ति पर्यवेक्षकों को जोड़ने में सक्षम कर सकते हैं।


7

स्विफ्ट में, यह दुर्भाग्य से करना संभव नहीं है। सबसे अच्छा विकल्प निम्नलिखित है:

class Jedi {
    private(set) var lightsaberColor = "Blue"
}


class Sith: Jedi {
    override var lightsaberColor : String {
        get {
            return "Red"
        }
    }
}

3

एक दृश्य नियंत्रक के लिए एक स्थिर सेट करने के लिए मुझे एक ही समस्या थी।

जैसा कि मैं दृश्य को प्रबंधित करने के लिए इंटरफ़ेस बिल्डर का उपयोग कर रहा हूं, मैं उपयोग नहीं कर सकता init(), इसलिए मेरा वर्कअराउंड अन्य उत्तरों के समान था, सिवाय इसके कि मैंने बेस और इनहेरिट की गई कक्षाओं में केवल पढ़ने योग्य कम्प्यूटेड चर का उपयोग किया।

class Jedi {
    var type: String {
        get { return "Blue" }
    }
}

class Sith: Jedi {
    override var type: String {
        get { return "Red" }
    }
}

3

यदि आप स्विफ्ट 5 में ऐसा करने का प्रयास करते हैं तो आपको ए द्वारा बधाई दी जाएगी

एक 'var' के गेट के साथ अपरिवर्तनीय 'लेट' प्रॉपर्टी 'lightSaberColor' को ओवरराइड नहीं कर सकते

आपकी सबसे अच्छी शर्त यह है कि इसे एक गणना की गई संपत्ति घोषित करें।

यह काम करता है क्योंकि हम केवल get {}फ़ंक्शन को ओवरराइड कर रहे हैं

class Base {
   var lightSaberColor: String { "base" }
}

class Red: Base {
   override var lightSaberColor: String { "red" }
}

2

स्विफ्ट आपको एक चर को ओवरराइड करने की अनुमति नहीं देता है stored propertyइसके बजाय आप इसका उपयोग कर सकते हैंcomputed property

class A {
    var property1 = "A: Stored Property 1"

    var property2: String {
        get {
            return "A: Computed Property 2"
        }
    }

    let property3 = "A: Constant Stored Property 3"

    //let can not be a computed property
    
    func foo() -> String {
        return "A: foo()"
    }
}

class B: A {

    //now it is a computed property
    override var property1: String {

        set { }
        get {
            return "B: overrode Stored Property 1"
        }
    }

    override var property2: String {
        get {
            return "B: overrode Computed Property 2"
        }
    }
    
    override func foo() -> String {
        return "B: foo()"
    }

    //let can not be overrode
}
func testPoly() {
    let a = A()
    
    XCTAssertEqual("A: Stored Property 1", a.property1)
    XCTAssertEqual("A: Computed Property 2", a.property2)
    
    XCTAssertEqual("A: foo()", a.foo())
    
    let b = B()
    XCTAssertEqual("B: overrode Stored Property 1", b.property1)
    XCTAssertEqual("B: overrode Computed Property 2", b.property2)
    
    XCTAssertEqual("B: foo()", b.foo())
    
    //B cast to A
    XCTAssertEqual("B: overrode Stored Property 1", (b as! A).property1)
    XCTAssertEqual("B: overrode Computed Property 2", (b as! A).property2)
    
    XCTAssertEqual("B: foo()", (b as! A).foo())
}

जावा के साथ तुलना करने पर यह अधिक स्पष्ट है, जहां एक वर्ग क्षेत्र को ओवररोड नहीं किया जा सकता है और बहुपत्नीवाद का समर्थन नहीं करता है क्योंकि संकलन समय (कुशलता से चलाने) में परिभाषित किया गया है। इसे एक चर छिपाना कहा जाता है [के बारे में] यह इस टेकनीक का उपयोग करने के लिए अनुशंसित नहीं है क्योंकि इसे पढ़ना / समर्थन करना कठिन है

[स्विफ्ट संपत्ति]


1

आप किसी कार्य को ओवरराइड करने के लिए भी उपयोग कर सकते हैं। यह प्रत्यक्ष उत्तर नहीं है, लेकिन इस विषय को समृद्ध कर सकता है)

कक्षा

override func viewDidLoad() {
    super.viewDidLoad()

    if shouldDoSmth() {
       // do
    }
}

public func shouldDoSmth() -> Bool {
    return true
}

कक्षा बी: ए

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