Ի՞նչ է խախտում ընտրովի գործառույթը պրոտոկոլում։
sobes.tech AI
Պատասխան AI-ից
Ավելացում պահանջների պրոտոկոլին այն բանից հետո, երբ այն սկսեցին օգտագործել այլ մոդուլներ կամ գրադարաններ: Եթե պրոտոկոլը արդեն ընդունված և իրականացված է, սովորական (չափազանցական) մեթոդների կամ հատկությունների ավելացումը կհանգեցնի կոդի սխալների բոլոր վայրերում, որտեղ օգտագործվում է պրոտոկոլը, մինչեւ նոր պահանջները կատարվեն:
Ընտրական պահանջները թույլ են տալիս ընդլայնել պրոտոկոլները, առանց գոյություն ունեցող իրականացմանը «վնասելու»: Կլասները կամ կառուցվածքները կարող են իրականացնել միայն մասամբ ընտրական մեթոդներ: Սա օգտակար է դելեգատորների հետ աշխատելիս կամ երբ ավելացվում են նոր ֆունկցիաներ արդեն կայացած API-ում:
Օրինակ՝ Objective-C-ում պրոտոկոլի ընտրական պահանջ (քանի որ Swift-ը չի աջակցում @optional առանց @objc):
// Swift-ում @optional-ը օգտագործվում է @objc պրոտոկոլի հետ
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 {
// Կոչում ենք ընտրական մեթոդը ստուգմամբ
delegate?.optionalMethod1?()
if let delegate = delegate {
if delegate.responds(to: #selector(delegate.optionalMethod2(value:))) {
delegate.optionalMethod2?(value: 10)
}
}
}
}
}
Swift-ում մաքուր պրոտոկոլները (առանց @objc) չեն աջակցում @optional-ին: Որպեսզի ունենաք ընտրական պահանջներ, պրոտոկոլը պետք է նշված լինի որպես @objc: Այդպիսի պրոտոկոլների իրականացմանը կարող են ավելացվել ընդլայնումներ՝ ընտրական մեթոդների իրականացման համար որպես նախնական, ինչը ավելի արդիական մոտեցում է Swift-ում:
Ստորև՝ Swift-ում պրոտոկոլների ընտրական վարքագիծը ընդլայնումների միջոցով՝
// Ավելի Swift-յան մոտեցում՝ պրոտոկոլների ընդլայնումներ՝ ըստ նախնական իրականացման
protocol MyProtocol {
func requiredMethod() -> Bool
func optionalMethod1()
func optionalMethod2(value: Int)
}
// Առանցքային իրականացումներ՝ որպես «ընտրական» մեթոդներ
extension MyProtocol {
func optionalMethod1() {
// Նախնական իրականացում կամ ստանդարտ վարք
print("Optional method 1 default implementation")
}
func optionalMethod2(value: Int) {
// Նախնական իրականացում
print("Optional method 2 default implementation with value: \(value)")
}
}
class MyClassSwift {
var delegate: MyProtocol?
func doSomething() {
if delegate?.requiredMethod() == true {
// Կոչում ենք մեթոդները առանց ստուգման, քանի որ դրանք կամ իրականացնում են, կամ օգտագործում են ընդլայնումից
delegate?.optionalMethod1()
delegate?.optionalMethod2(value: 20)
}
}
}
class MyCustomDelegate: MyProtocol {
func requiredMethod() -> Bool {
print("Required method implemented")
return true
}
// optionalMethod1() և optionalMethod2(value:) չեն պարտադիր իրականացնել,
// օգտագործվում է ընդլայնումից՝ նախնական իրականացում
// Բայց կարող եք վերականգնել դրանք՝ եթե այլ վարք եք ուզում:
// func optionalMethod1() {
// print("Custom implementation of optional method 1")
// }
}
let customDelegate = MyCustomDelegate()
let myClassSwift = MyClassSwift()
myClassSwift.delegate = customDelegate
myClassSwift.doSomething()
Այսպիսով, պրոտոկոլում ընտրական ֆունկցիայի ավելացումը՝ փորձել ավելացնել նոր պարտադիր պահանջ՝ արդեն օգտագործվող պրոտոկոլում, խախտում է հակադարձ համատեղելիությունը: Ընտրական պահանջները (առանց @objc կամ՝ ավելի լավ՝ ընդլայնումների միջոցով) կանխում են այս խախտումը։