通用类型与同一类型不同

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()
}