2017-05-09 17 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

相关问题