Kas pažeidžia pasirinktinę funkciją protokole?
sobes.tech AI
Atsakymas iš AI
Priklausomybės reikalavimų pridėjimas prie protokolo po to, kai jį pradėjo naudoti kiti moduliai ar bibliotekos. Jei protokolas jau priimtas ir įgyvendintas, įprastų (nepasirinktinių) metodų ar savybių pridėjimas sukels kompiliatoriaus klaidas visose vietose, kur naudojamas protokolas, kol šie nauji reikalavimai nebus įvykdyti:
Pasirinktinių reikalavimų leidžia plėsti protokolus, nepažeidžiant esamos įgyvendinimo. Klasės ar struktūros gali įgyvendinti tik dalį pasirinktinių metodų. Tai naudinga dirbant su delegatais arba pridedant naujų funkcijų jau susiformavusiame API:
Pavyzdys su Objective-C protokolu (kadangi Swift nepalaiko @optional be @objc):
// Swift'e `@optional` naudojamas su `@objc` protokolu
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 {
// Pasirinktinių metodų iškvietimas su patikra
delegate?.optionalMethod1?()
if let delegate = delegate {
if delegate.responds(to: #selector(delegate.optionalMethod2(value:))) {
delegate.optionalMethod2?(value: 10)
}
}
}
}
}
Swift'e švarūs protokolai (be @objc) nepalaiko @optional. Norint turėti pasirinktinius reikalavimus, protokolas turi būti pažymėtas kaip @objc. Tokie protokolai gali būti išplėsti, kad būtų galima pridėti pasirinktinių metodų numatytąją įgyvendinimą, kas yra modernesnis požiūris Swift'e:
Pavyzdys su protokolų išplėtimu Swift'e:
// Daug Swift-oviškesnis požiūris: protokolų išplėtimas su numatytomis įgyvendinimais
protocol MyProtocol {
func requiredMethod() -> Bool
func optionalMethod1()
func optionalMethod2(value: Int)
}
// Numatyti įgyvendinimai pasirinktiniams metodams
extension MyProtocol {
func optionalMethod1() {
// Numatyta įgyvendinimas arba standartinis elgesys
print("Optional method 1 default implementation")
}
func optionalMethod2(value: Int) {
// Numatyta įgyvendinimas
print("Optional method 2 default implementation with value: \(value)")
}
}
class MyClassSwift {
var delegate: MyProtocol?
func doSomething() {
if delegate?.requiredMethod() == true {
// Metodų iškvietimas be patikros dėl nil, nes jie arba įgyvendinti, arba naudoja iš išplėtimo
delegate?.optionalMethod1()
delegate?.optionalMethod2(value: 20)
}
}
}
class MyCustomDelegate: MyProtocol {
func requiredMethod() -> Bool {
print("Required method implemented")
return true
}
// optionalMethod1() ir optionalMethod2(value:) nėra privalomi įgyvendinti,
// bus naudojamas numatytas įgyvendinimas iš išplėtimo.
// Bet galima perrašyti juos, jei norite kitokio elgesio:
// func optionalMethod1() {
// print("Custom implementation of optional method 1")
// }
}
let customDelegate = MyCustomDelegate()
let myClassSwift = MyClassSwift()
myClassSwift.delegate = customDelegate
myClassSwift.doSomething()
Taigi, bandymas pridėti naują būtiną funkciją jau naudojamam protokolui, pažeidžia atgalinį suderinamumą. Pasirinktinių reikalavimų naudojimas (per @objc arba, dar geriau, per protokolų išplėtimus) tai išvengia.