你要找的是一個內部類(不一定是匿名的),它在一個範圍內聲明,它允許它訪問變量的MyClass
實例,並且採用在不同範圍定義的協議。現在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
實例,而不是MyView
實例「擁有」 Helper
實例。並且沒有辦法從Helper
的方法中引用該實例(或其屬性),因爲您可以在沒有現有的MyView
實例的情況下構建MyView.Helper()
。 Swift中的內部類(或通常嵌套類型)只能在詞法範圍內嵌套,而不能在存在所有權中嵌套。 (換句話說,因爲你引用了Java:Swift中的所有內部類都像Java中的靜態內部類,沒有非靜態的內部類。)如果這是你想要的功能,但是,it's probably worth telling Apple you want it。
你也可以嘗試在MyView.init()
裏面聲明Helper
- 在Swift中,你可以在任何地方嵌套類型定義,包括函數內部或其他類型的方法。在那裏定義,它可以參考MyView
的屬性。但是,現在Helper
的類型信息僅在MyView.init()
內部可見,所以當您將其分配給someComponent.delegate
(其類型僅爲SomeProtocol
)時,您無法使用它......甚至導致編譯器崩潰。 (這是另一個bug to report,但很難說錯誤是真的「編譯器崩潰的有效用法」或「代碼不好,但編譯器崩潰,而不是產生錯誤」。)
最接近的解決方案,我能想出看起來是這樣的:
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
時寫的封鎖,關閉那些可以捕捉你在哪裏調用初始化變量,包括指MyClass
實例創建Helper
隱含self
。
同時需要a0
/a1
和dec
/inc
,因爲你需要關閉(後者),而不是方法,捕捉封閉狀態。即使閉包和funcs /方法在很多方面是可以互換的,但是你不能通過給方法/ func名稱賦一個閉包來創建一個方法/ func實現。 (這將會是一個不同的故事,如果需要封閉性的,而不是方法SomeProtocol
,但我假設SomeProtocol
是不是你的控制之下的東西。)
無論如何,這是一種很多的樣板和一層您可能並不真正需要的抽象,因此可能需要尋找其他方法來構建代碼。
注:我的例子中使用了封閉{ self.count -= 1 }
下,您可能希望{ self.count-- }
。後者不起作用,因爲這是一個帶有值的表達式,所以Swift會將其解釋爲閉包返回值的簡寫。然後它會抱怨說,您爲() ->()
(又名Void -> Void
)關閉的房產分配了() -> Int
閉合。改用-= 1
來解決這個問題。
注意,所有上討論關閉其他問題的答案還解決您的問題關於「獲得變數協議範圍之內。」閉包可以捕獲和修改這些變量。 – 2014-09-07 02:38:09
謝謝我看這個解決方案,我沒有看到如何訪問父類的變量。 所有示例都顯示Anonymous類,但沒有一個示例訪問父變量。 – 2014-09-07 17:43:22