Čo porušuje voliteľnú funkciu v protokole?
sobes.tech AI
Odpoveď od AI
Pridanie požiadaviek k protokolu po tom, čo ho začali používať iné moduly alebo knižnice. Ak bol protokol už prijatý a implementovaný, pridanie bežných (nevoliteľných) metód alebo vlastností povedie k chybám pri kompilácii na všetkých miestach, kde sa protokol používa, kým tieto nové požiadavky nebudú splnené.
Voliteľné požiadavky umožňujú rozširovať protokoly bez "lámania" existujúcich implementácií. Triedy alebo štruktúry môžu implementovať iba časť voliteľných metód. To je užitočné pri práci s delegátmi alebo pri pridávaní nových funkcií do už zavedeného API.
Príklad voliteľnej požiadavky v protokole v Objective-C (pretože Swift nepodporuje @optional bez @objc):
// Vo Swift, `@optional` sa používa 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 {
// Volanie voliteľnej metódy s kontrolou
delegate?.optionalMethod1?()
if let delegate = delegate {
if delegate.responds(to: #selector(delegate.optionalMethod2(value:))) {
delegate.optionalMethod2?(value: 10)
}
}
}
}
}
Vo Swift, čisté protokoly (bez @objc) nepodporujú @optional. Aby mohli mať voliteľné požiadavky, protokol musí byť označený ako @objc. Implementácie takýchto protokolov môžu používať rozšírenia na pridanie predvolených implementácií voliteľných metód, čo je modernejší prístup v Swifte.
Príklad voliteľného správania cez rozšírenia protokolov v Swifte:
// Modernejší prístup: rozšírenia protokolov s predvolenými implementáciami
protocol MyProtocol {
func requiredMethod() -> Bool
func optionalMethod1()
func optionalMethod2(value: Int)
}
// Poskytujeme predvolené implementácie pre "voliteľné" metódy
extension MyProtocol {
func optionalMethod1() {
// Prázdna predvolená implementácia alebo štandardné správanie
print("Predvolená implementácia pre voliteľný 1")
}
func optionalMethod2(value: Int) {
// Prázdna predvolená implementácia
print("Predvolená implementácia pre voliteľný 2 s hodnotou: \(value)")
}
}
class MyClassSwift {
var delegate: MyProtocol?
func doSomething() {
if delegate?.requiredMethod() == true {
// Voláme metódy bez kontroly na nil, pretože
// buď sú implementované v triede/štruktúre, alebo sa používa
// implementácia z rozšírenia
delegate?.optionalMethod1()
delegate?.optionalMethod2(value: 20)
}
}
}
class MyCustomDelegate: MyProtocol {
func requiredMethod() -> Bool {
print("Požadovaná metóda implementovaná")
return true
}
// optionalMethod1() a optionalMethod2(value:) nie sú povinné na implementáciu,
// bude použitá predvolená implementácia z rozšírenia.
// Ale môžu byť prepísané, ak je potrebné iné správanie:
// func optionalMethod1() {
// print("Vlastná implementácia voliteľného 1")
// }
}
let customDelegate = MyCustomDelegate()
let myClassSwift = MyClassSwift()
myClassSwift.delegate = customDelegate
myClassSwift.doSomething()
Týmto spôsobom, pokus o pridanie novej povinnej funkcie do protokolu, ktorý je už používaný v kódovej základni, narúša spätnú kompatibilitu.