2014-09-06 15 views
6

我想懶/ inline在Swift中實現一個協議。 所以我將有機會獲得該協議範圍以外的變量的執行點,懶/ inline在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類,但沒有一個示例訪問父變量。

+0

注意,所有上討論關閉其他問題的答案還解決您的問題關於「獲得變數協議範圍之內。」閉包可以捕獲和修改這些變量。 – 2014-09-07 02:38:09

+0

謝謝我看這個解決方案,我沒有看到如何訪問父類的變量。 所有示例都顯示Anonymous類,但沒有一個示例訪問父變量。 – 2014-09-07 17:43:22

回答

3

你要找的是一個內部類(不一定是匿名的),它在一個範圍內聲明,它允許它訪問變量的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,其中selfHelper實例,而不是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是內部結構(可能是一類,而是一個結構是更簡單)
  • 它實現了a0a1方法,滿足的要求SomeProtocol
  • 個該的a0實現a1電話接到關閉decinc,這是本Helper結構的存儲特性(又名實例變量)
  • 當你構建一個Helper實例(使用你寫的(或規定),這些關閉默認成員明智的初始化,Helper(dec: (Void -> Void), inc: (Void -> Void))
  • 因爲你可以初始化Helper時寫的封鎖,關閉那些可以捕捉你在哪裏調用初始化變量,包括指MyClass實例創建Helper隱含self

同時需要a0/a1dec/inc,因爲你需要關閉(後者),而不是方法,捕捉封閉狀態。即使閉包和funcs /方法在很多方面是可以互換的,但是你不能通過給方法/ func名稱賦一個閉包來創建一個方法/ func實現。 (這將會是一個不同的故事,如果需要封閉性的,而不是方法SomeProtocol,但我假設SomeProtocol是不是你的控制之下的東西。)

無論如何,這是一種很多的樣板和一層您可能並不真正需要的抽象,因此可能需要尋找其他方法來構建代碼。


注:我的例子中使用了封閉{ self.count -= 1 }下,您可能希望{ self.count-- }。後者不起作用,因爲這是一個帶有值的表達式,所以Swift會將其解釋爲閉包返回值的簡寫。然後它會抱怨說,您爲() ->()(又名Void -> Void)關閉的房產分配了() -> Int閉合。改用-= 1來解決這個問題。

+0

謝謝!,很好的黑客:),這個例子可以爲我服務,爲什麼我需要'dec','inc'方法。我可以直接使用a0,01嗎?這是一個快速的限制嗎? – 2014-09-09 22:22:36

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 <如果需要,可以同時使用這種方式。

親切的問候