[英]Lazy/inline implement a protocol in Swift
我想懶惰/內聯在Swift中實現一個協議。 因此,在實現方面,我將訪問協議范圍之外的變量,
與在Java中實現接口而不聲明類相同:
class MyClass:UIView {
var someComponent:SomeInnerComponent = SomeInnerComponent();
var count:Int = 0;
var a = :SomeProtocol { //<----- IS THIS POSSIBLE, IF YES HOW ?
func a0() {MyClass.count--}
func a1() {MyClass.count++}
}
someComponenet.delegate = a;
}
protocol SomeProtocol {
func a0()
func a1()
}
編輯----
謝謝我看看這個解決方案,我沒有看到如何訪問父類的變量。 所有示例都顯示了一個Anonymous類,但沒有一個示例正在訪問父變量。
你正在尋找的是一個內部類(不一定是匿名的),在一個范圍內聲明,它允許它訪問MyClass
實例的count
變量,並采用在不同范圍定義的協議。 現在,Swift有一些這樣的部分,但看起來你不能把它們全部放在一起,就像你可能正在尋找的那樣簡潔。
您可能會考慮聲明一個內部類:
class MyView: UIView {
let someComponent = SomeInnerComponent() // type SomeInnerComponent is inferred
var count = 0 // type Int is inferred
class Helper: SomeProtocol {
func a0() { count-- } // ERROR
// ...
}
init() {
someComponent.delegate = Helper()
}
}
但這不起作用,因為count
是隱式self.count
,其中self
是Helper
實例,而不是“擁有” Helper
實例的MyView
實例。 並且沒有辦法在Helper
的方法中引用MyView
實例(或其屬性),因為您也可以在沒有現有MyView
實例的情況下構造MyView.Helper()
。 Swift中的內部類(或一般的嵌套類型)僅在詞法范圍內嵌套,而不是存在所有權。 (換句話說,因為你引用了Java:Swift中的所有內部類都像Java中的靜態內部類。沒有非靜態的內部類。)如果這是你想要的一個特性, 那么它可能值得講述蘋果你想要它 。
你也可以嘗試在MyView.init()
聲明Helper
- 在Swift中你可以在任何地方嵌套類型定義,包括內部函數或其他類型的方法。 在那里定義,它可以引用MyView
的屬性。 但是,現在Helper
的類型信息只能在MyView.init()
看到,所以當你將它分配給someComponent.delegate
(其類型只是SomeProtocol
)時,你無法使用它......這會導致崩潰編譯器,甚至。 (這是另一個要報告的錯誤 ,但是很難說這個錯誤是否真的“編譯器在有效使用時崩潰”或“代碼錯誤,但編譯器崩潰而不是產生錯誤”。)
我能想出的最接近的解決方案看起來像這樣:
class SomeInnerComponent {
var delegate: SomeProtocol?
}
protocol SomeProtocol {
func a0()
func a1()
}
class MyClass {
var someComponent = SomeInnerComponent()
var count = 0
struct Helper: SomeProtocol {
var dec: () -> ()
var inc: () -> ()
func a0() { dec() }
func a1() { inc() }
}
init() {
someComponent.delegate = Helper(
dec: { self.count -= 1 }, // see note below
inc: { self.count += 1 }
)
}
}
這個怎么運作:
Helper
是一個內部結構(可以是一個類,但結構更簡單) a0
和a1
方法,滿足了SomeProtocol
的要求 a0
和a1
的實現調用閉包dec
和inc
,它們是Helper
結構的存儲屬性(也就是實例變量) Helper
實例時(使用默認的成員初始化器, Helper(dec: (Void -> Void), inc: (Void -> Void))
您可以編寫(或以其他方式指定)這些閉包) Helper
時編寫閉包,所以這些閉包可以捕獲您調用初始化程序的變量,包括引用創建Helper
的MyClass
實例的隱式self
。 你需要a0
/ a1
和dec
/ inc
因為你需要閉包(后者)而不是方法來捕獲封閉狀態。 即使閉包和funcs /方法在很多方面可以互換,也不能通過為方法/ func名稱分配閉包來創建方法/ func實現。 (如果SomeProtocol
需要閉包屬性而不是方法,那將是一個不同的故事,但我假設SomeProtocol
不是你控制的東西。)
無論如何,這可能是一些你可能並不真正需要的樣板和抽象層,因此可能值得研究構建代碼的其他方法。
注意:我的示例使用了封閉{ self.count -= 1 }
,您可能期望{ self.count-- }
。 后者不起作用,因為這是一個帶有值的表達式,因此Swift會將其解釋為閉包的返回值的簡寫。 然后它會抱怨你為一個期望a () -> ()
(又名Void -> Void
)閉包的屬性分配了一個() -> Int
閉包。 使用-= 1
代替解決此問題。
我會采取不同的方法,我知道這是一個非常古老的話題,但以防其他人在這個問題上掙扎:
class MyClass:UIView {
var someComponent:SomeInnerComponent = SomeInnerComponent();
var count:Int = 0;
init(){
// Assign the delegate or do it somewhere else to your preference:
someComponenet.delegate = ProtocolImplementation(myClass: self);
}
private class ProtocolImplementation: SomeProtocol {
let selfReference: MyClass
init(myClass: MyClass){
selfReference = myClass
}
public func a0(){
selfReference.count--
}
public func a1(){
selfReference.count++
}
}
}
protocol SomeProtocol {
func a0()
func a1()
}
通過遵循這種方法,也可以多次包含相同的協議,假設您的協議支持通用,並且您希望實現它兩次。 如果需要,SomeProtocol <SomeObject>和SomeProtocol <OtherObject>都可以這種方式使用。
親切的問候
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.