2017-05-09 30 views
1

我有以下代碼:斯威夫特 - 如何定義一個類型約束保證類型有一個初始化

struct MyStruct { 
    var v: Int = 1 
} 

func createInstance<T: Any>(type: T.Type) -> T 
{ 
    return type.init() 
} 

let myType = MyStruct.self 
let instance = createInstance(type: myType) 

這不工作,因爲我不保證,將T有一個初始化。

Playground execution failed: error: MyPlayground.playground:76:12: error: type 'T' has no member 'init' 
return type.init() 
     ^~~~ ~~~~ 

但是我如何定義一個約束來保證類型有一個init?

+0

您可以使用這些結構和類必須實現的'Initializable'協議嗎? – NRitH

+0

你的意思只是一個空的協議,他們必須實現?嗯有點奇怪,但它聽起來像一個很好的伎倆:)我會試試看。 – Dareon

+0

你到底用'createInstance(type:)'實現了什麼?有一個原因是標準庫中沒有'DefaultConstructible'(或類似的)協議 - 沒有任何伴隨的語義,*只是*可初始化沒有意義。我建議讀一讀[協議不僅僅是語法](https://oleb.net/blog/2016/12/protocols-have-semantics/)。 – Hamish

回答

2

可以構建藍圖init()方法的自定義協議,並使用此協議爲您createInstance功能的通用typeholder類型約束。例如: -

protocol SimplyInitializable { 
    init() 
} 

struct MyStruct: SimplyInitializable { 
    var v: Int = 1 
} 

func createInstance<T: SimplyInitializable>(type: T.Type) -> T 
{ 
    return type.init() 
} 

let myType = MyStruct.self 
let instance = createInstance(type: myType) 

鍵入(明確)符合上述SimplyInitializable就能利用createInstance方法(注意MyStructSimplyInitializable一致性)。


正如上面的方法替代,你也同樣可以,如果你願意,利用一個通用struct而不是全球通用的createInstance方法來創建符合SimplyInitializable類型的實例。例如:

protocol SimplyInitializable { 
    init() 
} 

struct SimpleFactory<T: SimplyInitializable> { 
    static func createInstance() -> T { 
     return T.init() 
    } 
} 

struct MyStruct: SimplyInitializable { 
    var v: Int = 1 
} 

let instance = SimpleFactory<MyStruct>.createInstance() 
+0

完美,我錯誤地嘗試過使用func init()的協議。謝謝。 – Dareon

+0

@Dareon高興地幫助。請務必查看與Hamish鏈接的非常相關且相關的博客文章,以對上述問題發表評論。上面的答案顯示了你在技術上可以實現你所要求的功能,而博客文章則討論了爲什麼諸如上面的'SimplyInitializable'這樣的協議語義價值很差,並且實現例如'在Swift的stdlib中。 – dfri

相關問題