2017-02-20 44 views
2

在類中時,如何在聲明閉包參數時引用類本身?引用Swift中的自己的類型?

在下面的例子中,到位的Self使構建Foo當放置什麼類型的,封閉的參數也變得Foo同樣地,對於AnotherFoo

class FooBase { 
    init(completionHandler: (_ myself : Self)) { 
     // ... 
     self.completionHandler = completionHandler 
    } 

    var completionHandler : ((_ :Self) -> Void)? 

    func strategyMethod() { ... } 
} 

class Foo : FooBase { 
    // ... 
    override func strategyMethod() { 
     // do stuff 
     completionHandler?(self) 
    } 
} 

class AnotherFoo : FooBase { 
    // ... 
    override func strategyMethod() { 
     // do other stuff 
     completionHandler?(self) 
    } 
} 

func useFoos { 
    let foo = Foo(completionHandler: {(me : Foo) in 
     // ... 
    }) 
    let anotherFoo = AnotherFoo(completionHandler: {(me : AnotherFoo) in 
     // ... 
    }) 
} 
+0

連根拔起,因爲我不認爲你可以。希望這裏的真正的大師可以有更好的答案。在階級層次上,這是橫向的,正確的?這可以用任何語言來完成嗎? – dfd

+0

相關(dupe?):[init in params自身](http://stackoverflow.com/q/40055862/2976878)。但是你的配置無論如何都是不安全的 - 你不可能在非final類中有一個類型爲'((Self) - > Void)?'的存儲屬性。在'Foo'中,它可以保存'(Foo) - > Void'類型的值。但是如果你上傳到'FooBase',它現在被靜態類型爲'(FooBase) - > Void',這意味着你可以用AnotherFoo參數來調用它 - 這將是非法的('AnotherFoo'≠'Foo')。 – Hamish

+0

要完美*正確 - 我upvoted和拼寫正確使連根拔起。道歉。 – dfd

回答

1

我不認爲Swift允許你做你想做的事,但你可以關閉。

使用FooBase的類型,但你傳遞給初始化函數,投射到你知道的參數類型的倒閉是:

class FooBase { 
    init(completionHandler: @escaping (_ myself : FooBase) -> Void) { 
     // ... 
     self.completionHandler = completionHandler 
    } 

    var completionHandler : ((_ myself:FooBase) -> Void)? 

    func strategyMethod() { 
    } 
} 

class Foo : FooBase { 
    // ... 
    override func strategyMethod() { 
     // do stuff 
     completionHandler?(self) 
    } 
} 

class AnotherFoo : FooBase { 
    // ... 
    override func strategyMethod() { 
     // do other stuff 
     completionHandler?(self) 
    } 
} 

func useFoos() { 
    let foo = Foo(completionHandler: {(myself_in : FooBase) in 
     // This cast should always succeed when the closure is used as intended 
     if let myself = myself_in as? Foo { 
      // ... 
     } 
    }) 
    let anotherFoo = AnotherFoo(completionHandler: {(myself_in : FooBase) in 
     // This cast should always succeed when the closure is used as intended 
     if let myself = myself_in as? AnotherFoo { 
      // ... 
     } 
    }) 
}