Sobes.tech
Middle+

Co porušuje volitelnou funkci v protokolu?

sobes.tech AI

Odpověď od AI

Přidání požadavků do protokolu poté, co jej začaly používat jiné moduly nebo knihovny. Pokud byl protokol již přijat a implementován, přidání běžných (nevolitelných) metod nebo vlastností povede ke chybám při kompilaci na všech místech, kde je protokol používán, dokud tyto nové požadavky nebudou splněny.

Volitelné požadavky umožňují rozšiřovat protokoly, aniž by "lámaly" stávající implementace. Třídy nebo struktury mohou implementovat pouze část volitelných metod. To je užitečné při práci s delegáty nebo při přidávání nových funkcí do již zavedeného API.

Příklad volitelného požadavku v protokolu v Objective-C (protože Swift nepodporuje @optional bez @objc):

// Ve Swiftu se `@optional` používá s `@objc protocol`
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 {
            // Volání volitelné metody s kontrolou
            delegate?.optionalMethod1?()

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

Ve Swiftu čisté protokoly (bez @objc) nepodporují @optional. Aby bylo možné mít volitelné požadavky, musí být protokol označen jako @objc. Implementace takových protokolů může používat rozšíření k přidání výchozích implementací volitelných metod, což je modernější přístup ve Swiftu.

Příklad volitelného chování přes rozšíření protokolů ve Swiftu:

// Modernější přístup: rozšíření protokolů s výchozími implementacemi
protocol MyProtocol {
    func requiredMethod() -> Bool
    func optionalMethod1()
    func optionalMethod2(value: Int)
}

// Poskytujeme výchozí implementace pro "volitelné" metody
extension MyProtocol {
    func optionalMethod1() {
        // Prázdná výchozí implementace nebo standardní chování
        print("Výchozí implementace volitelné metody 1")
    }

    func optionalMethod2(value: Int) {
        // Prázdná výchozí implementace
        print("Výchozí implementace volitelné metody 2 s hodnotou: \(value)")
    }
}

class MyClassSwift {
    var delegate: MyProtocol?

    func doSomething() {
        if delegate?.requiredMethod() == true {
            // Voláme metody bez kontroly na nil, protože
            // buď jsou implementovány ve třídě/struktuře, nebo se používá
            // implementace z rozšíření
            delegate?.optionalMethod1()
            delegate?.optionalMethod2(value: 20)
        }
    }
}

class MyCustomDelegate: MyProtocol {
    func requiredMethod() -> Bool {
        print("Požadovaná metoda implementována")
        return true
    }

    // optionalMethod1() a optionalMethod2(value:) není nutné implementovat,
    // bude použita výchozí implementace z rozšíření.
    // Může být přepsána, pokud je potřeba jiné chování:
    // func optionalMethod1() {
    //     print("Vlastní implementace volitelné metody 1")
    // }
}

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

Tímto způsobem porušení volitelné funkce v protokolu při pokusu přidat novou povinnou požadavek k již existujícímu protokolu, který je používán v kódové základně, je zabráněno.