无法通过泛型方式带参初始化实体类:编译错误求解
你的问题出在泛型函数中调用初始化器的方式上——虽然已经给泛型参数EntityType加上了EntityCreatorInitializable协议约束,但直接用EntityType(entityCreator: self)这种方式调用初始化器,编译器无法在泛型上下文中正确解析这个调用逻辑。
先看你提供的原始代码:
protocol EntityCreator: class { func createEntity<EntityType: EntityClass & EntityCreatorInitializable>(type: EntityType.Type, _ initialize: @escaping (EntityType) -> Void) } protocol EntityCreatorInitializable { init(entityCreator: EntityCreator) } class EntityClass: NSObject { } class MyClass: EntityClass, EntityCreatorInitializable { required init(entityCreator: EntityCreator) { super.init() // use the entity creator } } // Entity creator implementation class EntityCreatorImplementation: EntityCreator { var toAdd = Set<EntityClass>() func createEntity<EntityType: EntityClass & EntityCreatorInitializable>(type: EntityType.Type, _ initialize: @escaping (EntityType) -> Void) { // 原代码初始化失败的位置 let newEntity = EntityType(entityCreator: self) initialize(newEntity) self.toAdd.insert(newEntity) } }
编译时触发的错误:
Non-nominal type 'EntityType' does not support explicit initialization
解决方案
只需要修改初始化器的调用方式,通过传入的type元类型来调用初始化方法,把EntityType(entityCreator: self)替换成type.init(entityCreator: self)即可。
修改后的createEntity函数代码:
func createEntity<EntityType: EntityClass & EntityCreatorInitializable>(type: EntityType.Type, _ initialize: @escaping (EntityType) -> Void) { let newEntity = type.init(entityCreator: self) initialize(newEntity) self.toAdd.insert(newEntity) }
原因解释
在Swift泛型函数的上下文里,直接通过泛型参数EntityType调用初始化器时,编译器无法百分百确认这个泛型类型确实严格遵循了协议的初始化要求(哪怕你加了约束,泛型的类型解析逻辑也需要更明确的元类型实例来锚定)。而传入的type参数是EntityType.Type的实例,也就是该泛型类型的元类型,通过它调用init方法,编译器可以明确确认这个类型实现了EntityCreatorInitializable协议的初始化器,从而正常完成调用。
另外补充说明:你提到实际项目中EntityClass是GKEntity,用NSObject复现问题一致,这个修改方案完全适用——核心问题是泛型初始化的调用方式,和具体父类无关。
内容的提问来源于stack exchange,提问作者zarghol

