为什么where子句仅对具有泛型参数的函数有效?

时间:2017-08-14 17:31:29

标签: swift generics

这个方法签名在Swift 4中无法编译似乎很荒谬:

class Bar<ValueType> { 
    func version() throws -> String where ValueType == [String: Any] { ... }
}   

(错误:where子句不能附加到非泛型声明)
但是编译得很好:

class Bar<ValueType> { 
   func version<T>(_ foo: T? = nil) throws -> String where ValueType == [String: Any] { ... }  
} 

任何人都可以了解为何会出现这种情况?

2 个答案:

答案 0 :(得分:2)

因为ValueType与此方法无关(在第一个示例中)。将这样的方法放在类型(class / struct / enum)中是错误的,因为它实际上并不是该类型的真正成员。它有条件地是该类型的成员,具体取决于where子句的真值。

要实现这一点,您可以使用所需的where子句将此方法放在类型的扩展名中。 E.g。

extension YourType where ValueType == [String: Any] {
    func version() throws -> String { ... }
}

答案 1 :(得分:1)

Swift 5.3 终于允许了。请参阅官方语言指南中的Contextual Where Clauses

从那里引用:

当您已经在泛型类型的上下文中工作时,可以将泛型where编写为声明的一部分,该声明没有自己的泛型类型约束。例如,您可以在通用类型的下标或通用类型扩展的方法上编写通用where子句。

...

extension Container {
    func average() -> Double where Item == Int {
        var sum = 0.0
        for index in 0..<count {
            sum += Double(self[index])
        }
        return sum / Double(count)
    }

在Xcode 12 beta 4中可以正常编译,但在Swift 5.2.4随附的Xcode 11.6中无法正常工作。