Sobes.tech
Middle+

Mis rikub valikulise funktsiooni protokollis?

sobes.tech AI

Vastus AI-lt

Nõuete lisamine protokollile pärast seda, kui seda on hakanud kasutama teised moodulid või teegid. Kui protokoll on juba vastu võetud ja rakendatud, tavaliste (mittevalikuliste) meetodite või omaduste lisamine põhjustab kõigis kohtades kompileerimisvigu, kus protokoll on kasutusel, kuni need uued nõuded täidetakse:

Valikulised nõuded võimaldavad protokolle laiendada, kahjustamata olemasolevat rakendust. Klasid või struktuure saab rakendada ainult osaliselt valikulisi meetodeid. See on kasulik töötades delegaatidega või lisades juba kehtivale API-le uusi funktsioone:

Näide Objective-C protokollist valikulise nõudena (kuna Swift ei toeta @optional ilma @objc-ta):

// Swiftis kasutatakse `@optional` koos `@objc` protokolliga
import Foundation

@objc protocol MyDelegate {
    func requiredMethod() -> Bool

    @optional func optionalMethod1()
    @optional func optionalMethod2(value: Int)
}

class MyClass {
    weak var delegate: MyDelegate?

    func doSomething() {
        if delegate?.requiredMethod() == true {
            // Valikulise meetodi väljakutse kontrolliga
            delegate?.optionalMethod1?()

            if let delegate = delegate {
                if delegate.responds(to: #selector(delegate.optionalMethod2(value:))) {
                    delegate.optionalMethod2?(value: 10)
                }
            }
        }
    }
}

Swiftis ei toeta puhtaid protokolle (ilma @objc-ta) @optional-i. Valikuliste nõuete jaoks peab protokoll olema märgitud @objc. Selliseid protokolle saab laiendada, lisades vaikimisi rakendused valikulistele meetoditele, mis on kaasaegsem lähenemine Swiftis:

Näide protokollide laiendamisest Swiftis:

// Veel Swift-ile lähem lähenemine: protokollide laiendused vaikimisi rakendustega
protocol MyProtocol {
    func requiredMethod() -> Bool
    func optionalMethod1()
    func optionalMethod2(value: Int)
}

// Vaikimisi rakendused valikulistele meetoditele
extension MyProtocol {
    func optionalMethod1() {
        // Vaikimisi rakendus või standardkäitumine
        print("Optional method 1 default implementation")
    }

    func optionalMethod2(value: Int) {
        // Vaikimisi rakendus
        print("Optional method 2 default implementation with value: \(value)")
    }
}

class MyClassSwift {
    var delegate: MyProtocol?

    func doSomething() {
        if delegate?.requiredMethod() == true {
            // Meetodite väljakutse ilma nil-i kontrollita, kuna need
            // või on rakendatud klassis/struktuuris, või kasutatakse
            // laiendist saadud rakendust
            delegate?.optionalMethod1()
            delegate?.optionalMethod2(value: 20)
        }
    }
}

class MyCustomDelegate: MyProtocol {
    func requiredMethod() -> Bool {
        print("Required method implemented")
        return true
    }

    // valikulised meetodid ei ole kohustuslikud rakendada,
    // kasutatakse vaikimisi rakendust laiendusest
    // Kuid neid saab üle kirjutada, kui soovite teistsugust käitumist:
    // func optionalMethod1() {
    //     print("Custom implementation of optional method 1")
    // }
}

let customDelegate = MyCustomDelegate()
let myClassSwift = MyClassSwift()
myClassSwift.delegate = customDelegate
myClassSwift.doSomething()

Seega, katse lisada juba kasutusel oleva protokolli uus kohustuslik nõue rikub tagasipööratava ühilduvuse. Valikuliste nõuete kasutamine (@objc kaudu või protokollide laienduste kaudu) seda takistab.