使用泛型和闭包编译错误来初始化类实例

时间:2014-07-14 11:10:00

标签: swift

我要做的是将一个闭包注入类初始值设定项,以便我可以从外部控制其初始化

我已经定义了一个必须由我想要初始化的类实现的协议:

protocol EntityInitializable {
    typealias T : EntityInitializable
    init(initializer: (T) -> ())
}

和一个试图注入闭包的函数

class EntityMapper<T : EntityInitializable> {
    func f() -> T {
        var cb = {(entity: T) -> () in
        }

        return T(cb)
    }
}

这会在编译期间生成以下错误:

  

错误:无法转换表达式&#39; T.T&#39;输入&#39; T&#39;           返回T(cb)

如果我修改上面的代码删除泛型部分,例如:

class MyClass {
    init(initializer: (MyClass) -> ()) {
    }
}

class EntityMapper {
    func f() -> MyClass {
        var cb = {(entity: MyClass) -> () in
        }

        return MyClass(cb)
    }
}

它有效。

对于什么是错误的任何想法?是因为我试图通过创建泛型的实例并使用相同泛型类型的参数传递闭包来尝试递归使用泛型?

1 个答案:

答案 0 :(得分:1)

您的代码不起作用的原因是没有任何内容表示T EntityInitializable(为清楚起见,我将从此处称之为EntityType)必须等于实现协议的类型。这是一个可以解释这个问题的例子:

class A: EntityInitializable {
    typealias EntityType = B
    init(initializer: (EntityType) -> ()) {

    }
}

class B: EntityInitializable {
    // [...]
}

根据您编写的代码,这完全没问题,这就是编译器不接受cb闭包的原因。其entity参数的类型为T,而EntityInitializable期望其类型为T.EntityType

编写此代码的正确方法是使用Self表示实现协议的类:

protocol EntityInitializable {
    init(initializer: (Self) -> ())
}