Swift - 如何定义类型约束以保证类型具有 init

Dar*_*eon 2 generics swift

我有以下代码:

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)
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为我不保证,T 有一个 init。

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

但是我如何定义一个约束来保证类型有一个 init 呢?

dfr*_*fri 6

可以构建一个自定义协议来绘制该init()方法的蓝图,并将该协议用作createInstance函数中泛型类型持有者的类型约束。例如:

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)
Run Code Online (Sandbox Code Playgroud)

(明确)符合SimplyInitializable上述的类型将能够使用该createInstance方法(注意符合MyStructto SimplyInitializable)。


作为上述方法的替代方法,如果您愿意,同样可以使用泛型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()
Run Code Online (Sandbox Code Playgroud)

  • @dfri 这些可能具有较差的泛型值,但是 c# 通过提供一个 `new()` 泛型类型约束非常优雅地解决了这个问题 (2认同)