2017-08-29 44 views
0

我有一個抽象class這樣定義的:創建一個工廠方法返回通用

class BaseCoordinator<ResultType> 

其它類從這一個如繼承。

final class AppCoordinator: BaseCoordinator<Void> 
final class AuthFlowCoordinator: BaseCoordinator<AuthFlowCoordinationResult> 
final class MainFlowCoordinator: BaseCoordinator<Void> 

現在我想創建一個工廠方法。我想這是sugnature應該是這樣的:

func makeCoordinator<T>() -> BaseCoordinator<T> 

但是,當然,我得到這樣的錯誤這一個:

Cannot convert return expression of type 'AppCoordinator' to return type 'BaseCoordinator<T>' 

什麼Xcode的建議我是添加as! BaseCoordinator<T>,但我討厭這種力量向下轉換(並返回?也不滿足我,因爲我100%肯定我會有一個正確的默認對象),因爲我想保證至少將返回一個默認的Coordinator
感覺就像我錯過了什麼,但我真的不知道它是什麼。實際上是可以做出這樣的工廠方法,還是Swift的泛型有限?

+0

您如何實施工廠方法?你只是檢查「T」是什麼,並返回相應子類的實例? – Sweeper

回答

2

T在編譯時必須有預定義的類型。因此,使用makeCoordinator()的實施方式,您不能通過返回具有不同ResultType s的不同協調員來選擇T

在這種情況下,呼叫者可以選擇他想分配給T的哪個值,這可能會破壞該功能。例如,下面的兩個調用將是非常有效:

let coordinator: BaseCoordinator<Void> = makeCoordinator() 
let coordinator: BaseCoordinator<[Int: [String]]> = makeCoordinator() 

這是沒有意義的使用[Int: [String]]作爲一種通用的類型,但它仍然是可能的。根據您在函數調用中選擇的泛型類型,演員陣營可能工作與否,這就是爲什麼演員陣容可能會導致崩潰。

按照Tom E的建議,可選的強制轉換將修復潛在的崩潰,但仍不能解決此問題。

因此,如果不使用工廠模式而不使用ResultTypeAny,則會使用包裝類型來打敗泛型的目的。

如果你想要類型安全,你必須爲你想要實例化的每個子類創建一個工廠方法,或者只需手動調用它們的初始化程序。

0

您可能想嘗試as?而不是as!。前者產生一個可選的,我。即如果演員不成功,結果將爲零。這樣你就可以安全地投射而不需要強迫任何東西。

+0

我知道我可以施放,但我必須返回可選。 – cojoj

+0

好吧,如果你「100%肯定我會有一個正確的默認對象」,那麼我會說,強制使用'as!'強制轉換返回類型是完全合理的。 –