通用类型与同一类型不同
Generic type not identical to the same type
我有以下内容(我已将其简化为最基本的情况):
class Something<H: Hashable> {
}
func function<H: NSDate>() -> Something<H> {
let s: Something<NSDate> = Something()
return s
}
错误在 return s
行:
NSDate is not identical to 'H'
但这没有任何意义,因为 NSDate
的任何子类或 NSDate
本身都应该被它允许。
例如以下作品:
let dateSomething: Something<NSDate> = Something()
functionWorks(dateSomething)
func functionWorks<H: NSDate>(parameter: Something<H>) {
}
有人知道为什么第一个示例不起作用吗?我目前认为这可能是 Swift 本身的问题...
通用类型参数不统一。只有在特化泛型时才会检查类型约束,否则在尖括号内具有不同内容的两个 thing<T>
是完全不相关的类型,即使尖括号内的内容本身是相关类型。
换句话说:Swift 泛型是类型保留。如果有人调用 function<SubclassOfNSDate>()
,它需要 return Something<SubclassOfNSDate>
,而不是 Something<NSDate>
。对于 return 后者将删除调用者提供的类型。 (其他一些语言使用 类型擦除 来实现泛型,所以你可以在那里这样做。但是类型擦除系统还有其他缺点,所以 Swift 不会那样做。)
很难从您发布的内容中看出您真正想在这里完成什么。不过,更改这一行至少应该可以编译:
let s: Something<H> = Something()
这样您就可以使用函数的通用参数(这是您期望的 return)中的 H
(恰好是 NSDate
)。
它不起作用,因为调用函数的特定子类型 H
可能是 NSDate
子类:
// subclass NSDate
class SpecialDate : NSDate { }
// this needs a Something<SpecialDate> returned, not a Something<NSDate>
let specialSomething: Something<SpecialDate> = function()
解决方案是在您的函数中使用 H
子类型 Something
:
func function<H: NSDate>() -> Something<H> {
let s: Something<H> = Something()
return s
}
回到你想要的:
func function<H: NSDate>() -> Something<H> {
正如 Nate 和 rickster 所指出的,由于 Swift 的类型规则,这将不起作用。但这也不是你真正的意思。没有理由使用类型参数化来指示一种特定类型。你不需要说 "H, where H is NSDate." 你应该说 "NSDate." 你真正的意思是:
func function() -> Something<NSDate> {
这样就可以了。其实因为类型推断,就更简单了:
func function() -> Something<NSDate> {
return Something()
}
我有以下内容(我已将其简化为最基本的情况):
class Something<H: Hashable> {
}
func function<H: NSDate>() -> Something<H> {
let s: Something<NSDate> = Something()
return s
}
错误在 return s
行:
NSDate is not identical to 'H'
但这没有任何意义,因为 NSDate
的任何子类或 NSDate
本身都应该被它允许。
例如以下作品:
let dateSomething: Something<NSDate> = Something()
functionWorks(dateSomething)
func functionWorks<H: NSDate>(parameter: Something<H>) {
}
有人知道为什么第一个示例不起作用吗?我目前认为这可能是 Swift 本身的问题...
通用类型参数不统一。只有在特化泛型时才会检查类型约束,否则在尖括号内具有不同内容的两个 thing<T>
是完全不相关的类型,即使尖括号内的内容本身是相关类型。
换句话说:Swift 泛型是类型保留。如果有人调用 function<SubclassOfNSDate>()
,它需要 return Something<SubclassOfNSDate>
,而不是 Something<NSDate>
。对于 return 后者将删除调用者提供的类型。 (其他一些语言使用 类型擦除 来实现泛型,所以你可以在那里这样做。但是类型擦除系统还有其他缺点,所以 Swift 不会那样做。)
很难从您发布的内容中看出您真正想在这里完成什么。不过,更改这一行至少应该可以编译:
let s: Something<H> = Something()
这样您就可以使用函数的通用参数(这是您期望的 return)中的 H
(恰好是 NSDate
)。
它不起作用,因为调用函数的特定子类型 H
可能是 NSDate
子类:
// subclass NSDate
class SpecialDate : NSDate { }
// this needs a Something<SpecialDate> returned, not a Something<NSDate>
let specialSomething: Something<SpecialDate> = function()
解决方案是在您的函数中使用 H
子类型 Something
:
func function<H: NSDate>() -> Something<H> {
let s: Something<H> = Something()
return s
}
回到你想要的:
func function<H: NSDate>() -> Something<H> {
正如 Nate 和 rickster 所指出的,由于 Swift 的类型规则,这将不起作用。但这也不是你真正的意思。没有理由使用类型参数化来指示一种特定类型。你不需要说 "H, where H is NSDate." 你应该说 "NSDate." 你真正的意思是:
func function() -> Something<NSDate> {
这样就可以了。其实因为类型推断,就更简单了:
func function() -> Something<NSDate> {
return Something()
}