如何为泛型函数foo约束Tkey与Entity的id类型一致?
解决方案
针对你的需求,只需在泛型函数的where子句中添加关联类型约束,就能把Tkey和T(遵循Entity的类型)的id属性类型绑定起来。
修改后的泛型函数
public func foo<T: AnyObject, Tkey>(id: Tkey) throws -> T? where T: Entity, T.T == Tkey { // 函数逻辑实现 }
关键说明
- 由于
T遵循Entity协议,它会自带协议中定义的关联类型T(也就是对应id的类型); - 通过
T.T == Tkey这个约束,直接强制Tkey必须和T的id类型完全一致。比如当T是Car时,T.T就是Int8,此时Tkey只能是Int8类型,编译器会自动校验类型匹配。
优化建议
原函数中id参数的类型是Any,建议改成Tkey,这样能充分利用类型约束的安全性,避免传入不符合要求的id类型。
示例调用
// 显式指定泛型参数 let car1 = try? foo<Car, Int8>(id: 5) // 利用Swift类型推断,省略泛型参数 let car2 = try? foo(id: Int8(10)) as Car?
可选的代码可读性优化
你的Entity协议里的关联类型命名为T容易和泛型参数混淆,建议改成更具语义的名字(比如IDType),修改后代码可读性会更高:
public protocol Entity { associatedtype IDType var id: IDType { get set } } open class EntityBase<ID>: Entity { public var id: ID } class Car: EntityBase<Int8> { var test: String }
对应的泛型函数可调整为:
public func foo<T: AnyObject, Tkey>(id: Tkey) throws -> T? where T: Entity, T.IDType == Tkey { // 函数逻辑实现 }
内容的提问来源于stack exchange,提问作者iamIcarus
相关产品推荐
相关产品推荐

