সুইফ্ট - শ্রেণির পদ্ধতি যা অবশ্যই সাবক্লাস দ্বারা ওভাররাইড করা উচিত


91

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


আপনি এটি সুপার ক্লাসে প্রয়োগ করতে এবং একটি দৃ as়তা তৈরি করতে পারেন। আমি ওবজ-সি, জাভা এবং পাইথনে এটি ব্যবহার করেছি।
ডেভিড স্ক্রান্ডজ

8
@ এনএসআরএ এটি একটি রানটাইম সৃষ্টি করে এবং একটি সংকলন সময় নয়, ত্রুটি
জুজোডি

এই উত্তর আপনাকে খুব সাহায্য করবে। লিঙ্কের বিবরণটি এখানে প্রবেশ করুন
চামথ জীবন

একটি বিশুদ্ধ ভার্চুয়াল ফাংশন দ্বারা বাস্তবায়িত হয় protocolগুলি (তুলনায় interfaceআপনি তাদের বিমূর্ত পদ্ধতি মত ব্যবহারের প্রয়োজন হলে জাভা গুলি) এই প্রশ্নের / উত্তর এ বর্ণন করেছেন: stackoverflow.com/a/39038828/2435872
jboi

উত্তর:


153

আপনার কাছে দুটি বিকল্প রয়েছে:

1. একটি প্রোটোকল ব্যবহার করুন

ক্লাসের পরিবর্তে প্রোটোকল হিসাবে সুপারক্লাসটি সংজ্ঞায়িত করুন

প্রো : প্রতিটি "সাবক্লাস" (প্রকৃত সাবক্লাস নয়) প্রয়োজনীয় পদ্ধতি (গুলি) প্রয়োগ করে কিনা তা পরীক্ষা করার জন্য সময় পরীক্ষা করুন

কন : "সুপারক্লাস" (প্রোটোকল) পদ্ধতি বা বৈশিষ্ট্যগুলি প্রয়োগ করতে পারে না

2. পদ্ধতির সুপার সংস্করণে দৃ As়তা দিন

উদাহরণ:

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

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

প্রো : সুপারক্লাসে পদ্ধতি এবং বৈশিষ্ট্যগুলি প্রয়োগ করতে পারে

কন : কোন সংকলন সময় চেক


4
@ জন্মে আপনি এখনও সাবক্লাসগুলিতে একটি সংকলন সময় চেক পাবেন না
22:30 এ অনুমান করুন

6
প্রোটোকল পদ্ধতিগুলি প্রয়োগ করতে পারে না তবে আপনি এর পরিবর্তে এক্সটেনশন পদ্ধতির মাধ্যমে সেগুলি সরবরাহ করতে পারেন।
ডেভিড মোলস

4
সুইফট ২.০ হিসাবে এখন প্রোটোকল এক্সটেনশনগুলিও রয়েছে: :) অ্যাপল রেফারেন্স
এফেমেরা

4
যদিও fatalErrorকম্পাইল-টাইম পরীক্ষণ উপলব্ধ করা হয় না, এটা যে কম্পাইলার অন্তত স্মার্ট যথেষ্ট এ পদ্ধতি যখন ফাঁসি পথ কলের জন্য একটি ফিরতি মান প্রদান করার প্রয়োজন না করা হয় সুন্দর fatalError
বগলুফ

4
কেস ২: সত্য মনে রাখবেন, আপনি যদি super.someFunc()ওভাররাইড হওয়া পদ্ধতি থেকে কল করেন তবে আপনি এটিকে ওভাররাইড করলেও ত্রুটি পাবেন। আপনি জানেন যে আপনি এটি কল করার জন্য ধারণা করছেন না, তবে অন্য কারও কাছে এটি জানতে হবে না এবং কেবল স্ট্যান্ডার্ড অনুশীলনটি অনুসরণ করা উচিত।
জাকুব ট্রুহলি

50

নিম্নলিখিতটি কোনও শ্রেণীর উত্তরাধিকার সূত্রে এবং প্রোটোকলের সংকলনের সময় পরীক্ষা করতে অনুমতি দেয় :)

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() { ... }

}

4
দুর্দান্ত, টাইপালিয়াসকে উদ্ধার করার জন্য :)
ক্রিস অলিনসন

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

@ ডেভিড রেক্টর, আপনি কি আপনার শ্রেণিটি ব্যক্তিগত এবং আপনার টাইপালিয়াসকে পাবলিক করতে সক্ষম? দুঃখিত আমার ফোন থেকে বার্তা, নিজেকে পরীক্ষা করতে পারবেন না।
স্কটিব্ল্যাডেস

4
নিখুঁত সমাধান, তার জন্য আপনাকে ধন্যবাদ। @ ডেভিডরেক্টর দ্বারা আন্ডারলাইন করা আছে, এটি কেবলমাত্র টাইপালিয়ালগুলি সর্বজনীন ছিল এমনটি করারও যদি কোনও সমাধান হয় তবে এটি দুর্দান্ত হবে, তবে দুর্ভাগ্যক্রমে এটি সম্ভব বলে মনে হচ্ছে না।
সাইবারড্যান্ডি

35

বিমূর্ত শ্রেণি / ভার্চুয়াল ফাংশনগুলির জন্য কোনও সমর্থন নেই, তবে আপনি সম্ভবত বেশিরভাগ ক্ষেত্রে একটি প্রোটোকল ব্যবহার করতে পারেন:

protocol SomeProtocol {
    func someMethod()
}

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

যদি সামারক্লাস কিছু ম্যাথড বাস্তবায়ন না করে তবে আপনি এই সংকলনের সময় ত্রুটিটি পাবেন:

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

30
নোট করুন এটি কেবলমাত্র শীর্ষস্থানীয় শ্রেণীর জন্য কাজ করে যা প্রোটোকল প্রয়োগ করে। যে কোনও সাবক্লাস প্রোটোকল প্রয়োজনীয়তা নির্লজ্জভাবে উপেক্ষা করতে পারে।
স্মৃতি

4
এছাড়াও, প্রোটোকলগুলিতে
জেনেরিকগুলি

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)
    }
}

4
আপনার আরও কয়েকটি ভার্চুয়াল পদ্ধতি থাকলে এতটা কার্যকর নয়
বুশরা শহিদ

@ xs2bush যদি আপনার আরও পদ্ধতিগুলি ভার্চুয়াল না হয় তবে এগুলি প্রোটোকলে ঘোষণা করা এবং এক্সটেনশন পদ্ধতির মাধ্যমে 'অ-ভার্চুয়াল' সরবরাহ করা ভাল better
ডেভিড মোলস

4
ঠিক কী আমি শেষ করে শেষ করেছি
বুশরা শহীদ

1

আপনি এখানে উত্তর দ্বারা প্রস্তাবিত হিসাবে প্রোটোকল বনাম দৃser়তা ব্যবহার করতে পারেন drewag। তবে, প্রোটোকলের জন্য উদাহরণ অনুপস্থিত। আমি এখানে আবরণ করছি,

প্রোটোকল

protocol SomeProtocol {
    func someMethod()
}

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

সংকলনের সময় পরীক্ষা করা প্রোটোকলটি এখন প্রতিটি সাবক্লাসকে প্রয়োগ করতে হবে। যদি সামারক্লাস কিছু ম্যাথড প্রয়োগ করে না, আপনি এই সংকলন সময় ত্রুটি পাবেন:

ত্রুটি: টাইপ 'সোমারস্লাস' প্রোটোকল 'সোমারপ্রোটোকল' এর সাথে খাপ খায় না

দ্রষ্টব্য: এটি কেবলমাত্র শীর্ষস্থানীয় শ্রেণীর জন্য কাজ করে যা প্রোটোকল প্রয়োগ করে। যে কোনও সাবক্লাস প্রোটোকল প্রয়োজনীয়তা নির্লজ্জভাবে উপেক্ষা করতে পারে। - যেমন মন্তব্য দ্বারাmemmons

দৃ .়তা

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

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

তবে দৃ .়তা কেবল রানটাইমে কাজ করবে।


-2

আইওএস বিকাশে নতুন হওয়ার কারণে, কখন এটি বাস্তবায়িত হয়েছিল তা আমি পুরোপুরি নিশ্চিত নই, তবে উভয় বিশ্বের সেরা পাওয়ার একটি উপায় হ'ল প্রোটোকলের জন্য একটি এক্সটেনশন বাস্তবায়ন করা:

protocol ThingsToDo {
    func doThingOne()
}

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

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

এক্সটেনশনটি আপনাকে ফাংশনটির জন্য ডিফল্ট মান রাখতে দেয় যখন নিয়মিত প্রোটোকলে ফাংশনটি এখনও সংজ্ঞায়িত না করে একটি সংকলন সময় ত্রুটি সরবরাহ করে


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