下面我有一个类,B
,具有泛型类型,并且泛型类型具有子类类型约束。在一个单独的类中,A
,我创建了一个字典属性,values
, 键为 String
值为 B
.类 A
then 有方法在字典中返回或设置值,这样值就不会被限制为单一类型(它们维护它们的通用 SomeType
类型,它是 NSObject
的子类)。但是,这会产生以下两个内联错误:
class A: NSObject {
var values = [String : B]()
func get<SomeType: NSObject>(key: String) -> B<SomeType>? {
// #1 Error on line below: cannot convert return expression of type 'B<NSObject>?' to return type 'B<SomeType>?'
return values[key]
}
func set<SomeType: NSObject>(key: String, value: B<SomeType>) {
// #2 Error on line below: cannot assign value of type 'B<SomeType>' to type 'B<NSObject>?'
values[key] = value
}
}
class B<SomeType: NSObject>: NSObject {
}
我尝试过各种形式的声明 values
告诉编译器 SomeType
的字典是 NSObject
的子类一切都会好起来的,但一直没有成功。类似于 this question ,我有点难过,因为这些方法定义了 SomeType
作为 NSObject
的子类因此在设置和获取 values
时,事情似乎是类型安全的.
我可以从方法中删除通用类型,而是强制类型为 <NSObject>
,但后来我遇到了与 here 相同的问题.
最佳答案
这可能与您认为的不同:
var values = [String : B]()
这不是真正的 [String : B]
,它是 [String : B<NSObject>]
. (我真的有点惊讶这是合法的语法;我很想打开一个关于它的错误报告;B
在 Swift 中不是一个合适的类型。)你可能已经意识到这一点,但它是第一个重要的注意。
第二个重要的注意事项是泛型类型在 Swift 中不是协变的。 Thing<Cat>
不是 Thing<Animal>
的子类型.这有一些类型理论的原因,也有一些技术实现的原因,但重要的事实是这在 Swift 中是不可能的。
如需持有多种B
类型,那么你需要构建一个 type eraser .在您的情况下,类型橡皮擦可能是 B<NSObject>
像这样:
class B<SomeType: NSObject>: NSObject {
let value: SomeType
init(value: SomeType) {
self.value = value
}
func liftGeneric() -> B<NSObject> {
return B<NSObject>(value: value)
}
}
如果你只需要持有一种 B
输入,然后生成 A
也通用。
关于ios - 使用泛型和访问字典值时的 Swift 编译时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41492183/