Sobes.tech
Middle+

Šta narušava opcionalnu funkciju u protokolu?

sobes.tech АИ

Одговор од АИ

Dodavanje zahteva u protokol nakon što ga koriste drugi moduli ili biblioteke. Ako je protokol već prihvaćen i implementiran, dodavanje običnih (neopcionih) metoda ili svojstava će dovesti do grešaka pri kompilaciji na svim mestima gde se protokol koristi, dok se ti novi zahtevi ne ispune.

Opcionalni zahtevi omogućavaju proširenje protokola bez "kvarenja" postojećih implementacija. Klase ili strukture mogu implementirati samo deo opcionalnih metoda. Ovo je korisno pri radu sa delegatima ili pri dodavanju novih funkcija u već uspostavljeni API.

Primer opcionalnog zahteva u protokolu u Objective-C (pošto Swift ne podržava @optional bez @objc):

// U Swift-u, `@optional` se koristi sa `@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 {
            // Pozivanje opcionalne metode sa proverom
            delegate?.optionalMethod1?()

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

U Swift-u, čisti protokoli (bez @objc) ne podržavaju @optional. Da bi imali opcionalne zahteve, protokol mora biti označen kao @objc. Implementacije takvih protokola mogu koristiti proširenja za dodavanje podrazumevanih implementacija opcionalnih metoda, što je moderniji pristup u Swift-u.

Primer opcionalnog ponašanja putem proširenja protokola u Swift-u:

// Moderniji pristup: proširenja protokola sa podrazumevanim implementacijama
protocol MyProtocol {
    func requiredMethod() -> Bool
    func optionalMethod1()
    func optionalMethod2(value: Int)
}

// Pružamo podrazumevane implementacije za "opcionalne" metode
extension MyProtocol {
    func optionalMethod1() {
        // Prazna podrazumevana implementacija ili standardno ponašanje
        print("Podrazumevana implementacija za opcionalni metod 1")
    }

    func optionalMethod2(value: Int) {
        // Prazna podrazumevana implementacija
        print("Podrazumevana implementacija za opcionalni metod 2 sa vrednošću: \(value)")
    }
}

class MyClassSwift {
    var delegate: MyProtocol?

    func doSomething() {
        if delegate?.requiredMethod() == true {
            // Pozivamo metode bez provere na nil jer
            // ili su implementirane u klasi/strukturi, ili se koristi
            // implementacija iz proširenja
            delegate?.optionalMethod1()
            delegate?.optionalMethod2(value: 20)
        }
    }
}

class MyCustomDelegate: MyProtocol {
    func requiredMethod() -> Bool {
        print("Obavezna metoda implementirana")
        return true
    }

    // optionalMethod1() i optionalMethod2(value:) nisu obavezni za implementaciju,
    // koristiće se implementacija iz proširenja.
    // Ali ih možete prepisati ako želite drugačije ponašanje:
    // func optionalMethod1() {
    //     print("Prilagođena implementacija opcionalnog metoda 1")
    // }
}

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

Na ovaj način, pokušaj dodavanja nove obavezne funkcije u protokol koji već postoji u kodnoj bazi narušava kompatibilnost unazad.