সুইফটে বিভিন্ন ধরণের সাথে সুপারক্লাস সম্পত্তি ওভাররাইড করা


129

সুইফ্টে, কেউ কী ব্যাখ্যা করতে পারবেন যে কীভাবে একটি সুপারক্লাসের কোনও সম্পত্তি মূল সম্পত্তি থেকে বিয়োগ করে অন্য কোনও বস্তুর সাথে ওভাররাইড করা যায়?

এই সহজ উদাহরণ নিন:

class Chassis {}
class RacingChassis : Chassis {}

class Car {
    let chassis = Chassis()
}
class RaceCar: Car {
    override let chassis = RacingChassis() //Error here
}

এটি ত্রুটি দেয়:

Cannot override with a stored property 'chassis'

পরিবর্তে যদি আমার চেসিসটি 'ভার' হিসাবে থাকে তবে আমি ত্রুটিটি পেয়েছি:

Cannot override mutable property 'chassis' of type 'Chassis' with covariant type 'RacingChassis'

"ওভাররাইডিং প্রোপার্টিস" এর অধীনে গাইডটিতে আমি কেবলমাত্র খুঁজে পেতে পারি তা নির্দেশ করে যে আমাদের গেটর এবং সেটারকে ওভাররাইড করতে হবে, যা সম্পত্তিটির মান পরিবর্তনের জন্য কাজ করতে পারে (যদি এটি 'ভ্যার' হয়) তবে সম্পত্তি শ্রেণীর পরিবর্তন সম্পর্কে কী বলা যায়? ?

উত্তর:


115

সুইফট আপনাকে কোনও চলক বা বৈশিষ্ট্য শ্রেণীর ধরণের পরিবর্তন করতে দেয় না। পরিবর্তে আপনি সাবক্লাসে একটি অতিরিক্ত ভেরিয়েবল তৈরি করতে পারেন যা নতুন শ্রেণীর ধরণের পরিচালনা করে:

class Chassis {}
class RacingChassis : Chassis {}

class Car {
    var chassis = Chassis()
}
class RaceCar: Car {
    var racingChassis = RacingChassis()
    override var chassis: Chassis {
        get {
            return racingChassis
        }
        set {
            if let newRacingChassis = newValue as? RacingChassis {
                racingChassis = newRacingChassis
            } else {
                println("incorrect chassis type for racecar")
            }
        }
    }
}

দেখে মনে হচ্ছে যে কোনও ব্যক্তি লেট সিনট্যাক্সের সাহায্যে কোনও সম্পত্তি ঘোষণা করতে পারে না এবং এটির সাবক্লাস বা তদ্বিপরীতভাবে এর পরিবর্তে ওভাররাইড করতে পারে না, কারণ এটি হতে পারে যে সুপারক্লাস বাস্তবায়নের ফলে সেই সম্পত্তিটি একবার শুরু হওয়ার পরিবর্তনের আশা করা যায় না। সুতরাং এক্ষেত্রে সাবক্লাসটি (উপরের স্নিপেটে দেখানো হয়েছে) মেলাতে সম্পত্তিটিকে সুপারক্লাসে 'ভার' দিয়ে ঘোষণা করা দরকার। যদি কেউ সুপারক্লাসে উত্স কোডটি পরিবর্তন করতে না পারে তবে বর্তমানের রেসকারটি ধ্বংস করা এবং চ্যাসিসকে পরিবর্তিত করার জন্য প্রত্যেকবার একটি নতুন রেসকার তৈরি করা সম্ভবত সেরা।


1
দুঃখিত শুধু আমার মন্তব্য মুছে ফেলুন এবং তারপরে আপনার উত্তরটি দেখেছেন। আমার একটি সমস্যা ছিল কারণ আমার বাস্তব ক্ষেত্রে আমার সুপারক্লাস একটি strongসম্পত্তি সহ একটি উদ্দেশ্যমূলক সি শ্রেণি এবং এটির উপর চাপ দেওয়ার চেষ্টা করেও আমি একটি ত্রুটি পেয়েছি - তবে মনে হচ্ছে আমি এটি মিস করেছি যে এটি একটি "স্পষ্টতভাবে মোড়কযুক্ত optionচ্ছিক" ( chassis!) তে অনুবাদ করে সুইফ্ট, সুতরাং override var chassis : Chassis!এটি ঠিক করুন।
জেমস

4
এটি আর এক্সকোড 6.1 এর অধীনে সুইফট 1.1 এর সাথে কাজ করে না। ত্রুটি উত্পন্ন করে: "একটি 'বার' এর সংযোজনকারীর সাথে অপরিবর্তনীয় 'সম্পত্তি' চ্যাসিস 'কে ওভাররাইড করা যায় না"। আরও ভাল সমাধানের জন্য কোন ধারণা?
দারারস্কি

1
এছাড়াও এক্সকোড 6.3 বিটার অধীনে সুইফট 1.2 তে আর কাজ করে না। কোভারিয়েন্ট টাইপ 'টাইপ 2' এর সাথে 'টাইপ 1' টাইপের বিভাজ্য সম্পত্তি 'এ' ওভাররাইড করা যায় না
বুবুকু

10
এটি সত্যিই খোঁড়া, এবং সুইফটের একটি ব্যর্থতা, ইমো। যেহেতু RacingChassis হয় একটি চ্যাসি, কম্পাইলার আপনি একটি উপশ্রেণী সম্পত্তি বর্গ পরিমার্জন করতে সক্ষম হবেন কোন সমস্যা থাকা উচিত। প্রচুর ভাষাগুলি এটিকে মঞ্জুরি দেয় এবং এটিকে সমর্থন না করা এর মতো কুৎসিত কাজের দিকে পরিচালিত করে। কোন অপরাধ। : /
devios1

1
বিকল্পগুলি প্রস্তাব দেওয়ার একটি উপায় সরবরাহ করে যে কোনও পরিবর্তনশীল উপস্থিত নাও হতে পারে কারণ এটি এমন কোনও ফাংশন দ্বারা সরবরাহ করা হয়েছিল যা প্রত্যাশিত মানটি আর দেয় না। ফাংশনটি ওভাররাইড করা থাকলে এই জাতীয় ঘটনাগুলি ঘটতে পারে। বিস্তারিত জানার জন্য আমার উত্তর একবার দেখুন।

10

এটি কাজ করে বলে মনে হচ্ছে

class Chassis {
    func description() -> String {
        return "Chassis"
    }
}
class RacingChassis : Chassis {
    override func description() -> String {
        return "Racing Chassis"
    }

    func racingChassisMethod() -> String {
        return "Wrooom"
    }
}

class Car {
    let chassis = Chassis()
}
class RaceCar: Car {
    override var chassis: RacingChassis {
    get {
        return self.chassis
    }
    set {
        self.chassis = newValue
    }
    }
}

var car = Car()
car.chassis.description()

var raceCar = RaceCar()
raceCar.chassis.description()
raceCar.chassis.racingChassisMethod()

1
এটি চ্যাসিস সম্পত্তি শ্রেণীর মতো সংজ্ঞায়িত হিসাবে letকাজ করে Carযা এটি পরিবর্তন করা অসম্ভব করে তোলে। আমরা কেবল শ্রেণীর chassisসম্পত্তি পরিবর্তন করতে পারি RaceCar
ডেভিড আরভ

4
এটি সুইফট ২.০ এর জন্য কাজ করে না। এটি "ত্রুটি দেয়: একটি 'ভার'" এর প্রাপকের সাথে অপরিবর্তনীয় 'সম্পত্তি' চ্যাসিসকে ওভাররাইড করতে পারে না
mohamede1945

এটি সুইচ ৪.০ তেও কাজ করে না। লেআগ্রাউন্ড এক্সিকিউশন ব্যর্থ হয়েছে: ত্রুটি: মাইপ্লেগ্রাউন্ডস.প্লেগ্রাউন্ড: 14: 15: ত্রুটি: 'ভার' ওভাররাইড ভেরি চেসিসের প্রাপ্তির সাথে অপরিবর্তনীয় 'সম্পত্তি' চ্যাসিসকে ওভাররাইড করতে পারে না: রেসিংচ্যাসিস ^ ^ মাইপ্লেগ্রাউন্ডস.প্লেগ্রাউন্ড: 11: 6: নোট : এখানে সম্পত্তি ওভাররাইড করার চেষ্টা চ্যাসিস = চ্যাসিস () ^
করিম

7

এটা চেষ্টা কর:

class Chassis{
     var chassis{
         return "chassis"
     } 
}

class RacingChassis:Chassis{
     var racing{
         return "racing"
     } 
}

class Car<Type:Chassis> {
     let chassis: Type
     init(chassis:Type){
        self.chassis = chassis
     }
}

class RaceCar: Car<RacingChassis> {
     var description{
         return self.chassis.racing
     } 
}

তারপর:

let racingChassis = RacingChassis()
let raceCar = RaceCar(chassis:racingChassis)
print(raceCar.description) //output:racing

বিশদ http://www.mylonly.com/14957025459875.html



3

সলিউশন ড্যাশ সরবরাহ করেছে সুপার ক্লাসটিকে বর্ণের পরিবর্তে লেট কীওয়ার্ড দিয়ে ঘোষণা করতে হবে except এখানে এমন একটি সমাধান রয়েছে যা সম্ভব তবে প্রস্তাবিত নয়!

নীচের সমাধানটি Xcode 6.2, SWIFT 1.1 দিয়ে সংকলিত হবে (যদি সব শ্রেণি আলাদা আলাদা swift ফাইলগুলিতে থাকে) তবে এড়ানো উচিত কারণ এটি অনিচ্ছুক আচরণগুলি (বিশেষতঃ অ-optionচ্ছিক প্রকারের ব্যবহারের সময় অন্তর্ভুক্ত থাকতে পারে) যেতে পারে। দ্রষ্টব্য: এটি এক্সকোড 6.3 বিটা 3, সুইফট 1.2 দিয়ে কাজ করে না

class Chassis {}
class RacingChassis : Chassis {}
class Car {
    var chassis:Chassis? = Chassis()
}

class RaceCar: Car {
    override var chassis: RacingChassis? {
        get {
            return super.chassis as? RacingChassis
        }
        set {
            super.chassis = newValue
        }
    }
}

1
এটি সুইফট ২.০ এর জন্য কাজ করে না। এটি দেয় "পরিবর্তিত সম্পত্তি 'চ্যাসিস' ধরণের 'চ্যাসিস' কে ওভাররাইড করতে পারে না? ' 'রেসিংচ্যাসিস?' সমবায়ু টাইপ সহ ""
mohamede1945

2

তাত্ত্বিকভাবে, আপনাকে এটি এইভাবে করার অনুমতি দেওয়া হয়েছে ...

class ViewController {

    var view: UIView! { return _view }

    private var _view: UIView!
}

class ScrollView : UIView {}

class ScrollViewController : ViewController {

    override var view: ScrollView! { return super.view as ScrollView! }
}

class HomeView : ScrollView {}

class HomeViewController : ScrollViewController {

    override var view: HomeView! { return super.view as HomeView! }
}

এটি একটি এক্সকোড খেলার মাঠে পুরোপুরি কাজ করে।

তবে , যদি আপনি এটি বাস্তব প্রকল্পে চেষ্টা করেন তবে একটি সংকলক ত্রুটি আপনাকে বলে:

ঘোষণা 'দর্শন' একাধিক সুপারক্লাস ঘোষণাকে ওভাররাইড করতে পারে না

আমি এখন পর্যন্ত কেবলমাত্র Xcode 6.0 GM পরীক্ষা করেছি।

দুর্ভাগ্যক্রমে, অ্যাপল এটি ঠিক না করা পর্যন্ত আপনাকে অপেক্ষা করতে হবে।

আমি একটি বাগ রিপোর্টও জমা দিয়েছি। 18518795


এটি একটি আকর্ষণীয় সমাধান, এবং এটি 6.1-এ কাজ করে।
ক্রিস কনভারের

1

আমি ফাংশনগুলির পরিবর্তে ভেরিয়েবল ব্যবহার করে এপিআই ডিজাইন করা সমস্যার কারণ হিসাবে অনেক কারণ দেখেছি এবং গণনা করা বৈশিষ্ট্যগুলি ব্যবহার করা আমার কাছে কার্যকারিতার মতো মনে হয়। আপনার দৃষ্টান্তের ভেরিয়েবলগুলি এনকেপসুলেটেড রাখার জন্য যথেষ্ট কারণ রয়েছে। এখানে আমি একটি প্রোটোকল অটোমোবাইল তৈরি করেছি যা গাড়ি অনুসারে চলে। এই প্রোটোকলের একটি অ্যাকসেসর পদ্ধতি রয়েছে যা একটি চ্যাসিস অবজেক্টকে ফেরত দেয়। যেহেতু গাড়ি এটিকে সম্মতি জানায় রেসকার সাবক্লাস এটিকে ওভাররাইড করতে পারে এবং একটি ভিন্ন চ্যাসিস সাবক্লাস ফিরে আসতে পারে। এটি কার শ্রেণিকে একটি ইন্টারফেসে প্রোগ্রাম করতে দেয় (অটোমোবাইল) এবং রেসিংচ্যাসিস সম্পর্কে জানে এমন রেসকার শ্রেণি সরাসরি _racingChassis পরিবর্তনশীল অ্যাক্সেস করতে পারে।

class Chassis {}
class RacingChassis: Chassis {}

protocol Automobile {
    func chassis() -> Chassis
}

class Car: Automobile {
    private var _chassis: Chassis

    init () {
        _chassis = Chassis()
    }

    func chassis() -> Chassis {
        return _chassis
    }
}

class RaceCar: Car {
    private var _racingChassis: RacingChassis

    override init () {
        _racingChassis = RacingChassis()
        super.init()
    }

    override func chassis() -> Chassis {
        return _racingChassis
    }
}

ভেরিয়েবলগুলি ব্যবহার করে কেন এপিআই ডিজাইন করা তার আরেকটি উদাহরণ হ'ল যখন আপনার কোনও প্রোটোকলে ভেরিয়েবল থাকে। আপনি যদি সমস্ত প্রোটোকল ফাংশনকে কোনও এক্সটেনশনে বিভক্ত করতে চান তবে সংরক্ষণকৃত সম্পত্তি ব্যতীত এক্সটেনশানগুলিতে স্থাপন করা যায় না এবং ক্লাসে সংজ্ঞায়িত করতে হয় (কোডটি সংকলনের জন্য এটি পেতে কোডটি অসাধারণ করতে হবে) অভিযোজিতভিউ কনট্রোলার ক্লাস এবং এক্সটেনশন থেকে মোড ভেরিয়েবল অপসারণ করুন:

protocol Adaptable {
    var mode: Int { get set }
    func adapt()
}

class AdaptableViewController: UIViewController {
    // var mode = 0
}

extension AdaptableViewController: Adaptable {

    var mode = 0 // compiler error

    func adapt() {
        //TODO: add adapt code
    }
}

উপরের কোডটিতে এই সংকলক ত্রুটি থাকবে: "এক্সটেনশনে স্টোরের বৈশিষ্ট্য নাও থাকতে পারে"। এখানে আপনি উদাহরণটি কীভাবে পুনরায় লিখতে পারেন যাতে প্রোটোকলের সমস্ত কিছুই এর পরিবর্তে ফাংশন ব্যবহার করে এক্সটেনশনে আলাদা করা যায়:

protocol Adaptable {
    func mode() -> Int
    func adapt()
}

class AdaptableViewController: UIViewController {
}

extension AdaptableViewController: Adaptable {
    func mode() -> Int {
        return 0
    }
    func adapt() {
        // adapt code
    }
}

1

আপনি জেনেরিক ব্যবহারের মাধ্যমে এটি অর্জন করতে পারেন:

class Descriptor {
    let var1 = "a"
}

class OtherDescriptor: Descriptor {
    let var2 = "b"
}

class Asset<D: Descriptor> {
    let descriptor: D

    init(withDescriptor descriptor: D) {
        self.descriptor = descriptor
    }

    func printInfo() {
        print(descriptor.var1)
    }
}

class OtherAsset<D: OtherDescriptor>: Asset<D> {
    override func printInfo() {
        print(descriptor.var1, descriptor.var2)
    }
}

let asset = Asset(withDescriptor: Descriptor())
asset.printInfo() // a

let otherAsset = OtherAsset(withDescriptor: OtherDescriptor())
otherAsset.printInfo() // a b

এই পদ্ধতির সাহায্যে আপনার 100% প্রকারের নিরাপদ কোডটি জোর করে আনপ্রেপ ছাড়াই থাকবে।

তবে এটি হ্যাকের মতো এবং আপনার যদি শ্রেণীর ঘোষণাপত্রের চেয়ে বেশ কয়েকটি সম্পত্তি পুনরায় সংজ্ঞায়িত করতে হয় তবে এটি সম্পূর্ণ গণ্ডগোলের মতো দেখাবে। সুতরাং এই পদ্ধতির সাথে সতর্কতা অবলম্বন করুন।


1

আপনি কীভাবে সম্পত্তি ব্যবহারের পরিকল্পনা করছেন তার উপর নির্ভর করে এটি করার সহজতম উপায় হ'ল আপনার সাবক্লাসের জন্য একটি optionচ্ছিক প্রকার ব্যবহার করা, এবং সুপারের জন্য didSet {}পদ্ধতিটি ওভাররাইড করা :

class Chassis { }
class RacingChassis: Chassis { }

class Car {
    // Declare this an optional type, and do your 
    // due diligence to check that it's initialized
    // where applicable
    var chassis: Chassis?
}
class RaceCar: Car {
    // The subclass is naturally an optional too
    var racingChassis: RacingChassis?
    override var chassis: Chassis {
        didSet {
            // using an optional, we try to set the type
            racingChassis = chassis as? RacingChassis
        }
    }
}

অবশ্যই ক্লাসগুলি এভাবে শুরু করা যেতে পারে তা নিশ্চিত করার জন্য আপনাকে কিছুটা সময় ব্যয় করতে হবে তবে বৈশিষ্ট্যগুলি propertiesচ্ছিকভাবে সেট করে আপনি নিজেকে এমন পরিস্থিতিতে রক্ষা করুন যেখানে কাস্টিং আর কাজ করে না।


0

আপনি কেবল রেসিংচ্যাসিসের আরেকটি পরিবর্তনশীল তৈরি করতে পারেন।

class Chassis {}
class RacingChassis : Chassis {}
class Car {
    let chassis: Chassis
    init(){
        chassis = Chassis()
}}

class RaceCar: Car {
let raceChassis: RacingChassis
init(){
        raceChassis = RacingChassis()
}}

এটি কাজ করে, তবে আমি মনে করি ড্যাশের উত্তরটি সম্পত্তিটির সাথে chassisআমাদের RacingChassisউদাহরণটি পেতে / সেট করার অনুমতি দিয়ে ওভাররাইড করে এবং আরও এক ধাপ এগিয়ে নিয়ে যায় chassis
জেমস

0

এটা চেষ্টা কর:

class Chassis {}
class RacingChassis : Chassis {}
class SuperChassis : RacingChassis {}

class Car {
    private var chassis: Chassis? = nil
    func getChassis() -> Chassis? {
        return chassis
    }

    func setChassis(chassis: Chassis) {
        self.chassis = chassis
    }
}

class RaceCar: Car {
    private var chassis: RacingChassis {
        get {
            return getChassis() as! RacingChassis
        }
        set {
            setChassis(chassis: newValue)
        }
    }

    override init() {
        super.init()

        chassis = RacingChassis()
    }
}

class SuperCar: RaceCar {
    private var chassis: SuperChassis {
        get {
            return getChassis() as! SuperChassis
        }
        set {
            setChassis(chassis: newValue)
        }
    }

    override init() {
        super.init()

        chassis = SuperChassis()
    }
}

0
class Chassis {}
class RacingChassis : Chassis {}

class Car {
    fileprivate let theChassis: Chassis
    var chassis: Chassis {
        get {
            return theChassis
        }
    }
    fileprivate init(_ chassis: Chassis) {
        theChassis = chassis
    }
    convenience init() {
        self.init(Chassis())
    }
}
class RaceCar: Car {
    override var chassis: RacingChassis {
        get {
            return theChassis as! RacingChassis
        }
    }
    init() {
        super.init(RacingChassis())
    }
}

0

নিম্নলিখিতটি কোনও একক বস্তুকে বেস এবং উত্পন্ন ক্লাসে ব্যবহার করার অনুমতি দেয়। উদ্ভূত শ্রেণিতে, উত্পন্ন বস্তুর সম্পত্তি ব্যবহার করুন।

class Car {
    var chassis:Chassis?

    func inspect() {
        chassis?.checkForRust()
    }
}

class RaceCar: Car {
    var racingChassis: RacingChassis? {
        get {
            return chassis as? RacingChassis
        } 
    }

    override func inspect() {
        super.inspect()
        racingChassis?.tuneSuspension()
    }
}

0

অন্যান্য উত্তরের একটি সামান্য প্রকরণ, তবে কিছু দুর্দান্ত সুবিধা সহ সহজ এবং নিরাপদ।

class Chassis {}
class RacingChassis : Chassis {}

class Car {
    let chassis = Chassis()
}
class RaceCar: Car {
    var racingChassis: RacingChassis? {
        get {
            return chassis as? RacingChassis
        }
    }
}

সুবিধাগুলির মধ্যে রয়েছে যে চ্যাসিসটি অবশ্যই হবে (var, let, alচ্ছিক, ইত্যাদি) এর উপর কোনও বিধিনিষেধ নেই এবং এটি সাবক্লাস রেসকার সহজ। রেসকারের সাবক্লাসগুলি চ্যাসিস (বা রেসিংচ্যাসিস) এর জন্য তাদের নিজস্ব গণিত মান থাকতে পারে।


-2

ইমগভিউয়ের মতো বিভিন্ন নামকরণের কনভেনশন সহ কেবলমাত্র নতুন চিত্রদর্শন সম্পত্তি সেট করুন কারণ ইমেজভিউ ইতিমধ্যে এর নিজস্ব সম্পত্তি এবং আমরা 2 টি শক্তিশালী সম্পত্তি বরাদ্দ করতে পারি না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.