【发布时间】:2017-10-18 12:18:08
【问题描述】:
这两种声明泛型超类的方法有或没有'where'子句有什么区别?
func foo<T: SomeClass>(object: T) -> Array<T>
func foo<T>(object: T) -> Array<T> where T: SomeClass
【问题讨论】:
这两种声明泛型超类的方法有或没有'where'子句有什么区别?
func foo<T: SomeClass>(object: T) -> Array<T>
func foo<T>(object: T) -> Array<T> where T: SomeClass
【问题讨论】:
这在Swift guide中有明确说明:
通用 where 子句中的要求指定一个类型 参数继承自类或符合协议或协议 作品。虽然通用的 where 子句提供了句法 用于表达对类型参数的简单约束的糖(对于 例如,
<T: Comparable>等价于<T> where T: Comparable和 等等),您可以使用它来提供更复杂的类型约束 参数及其相关类型。例如,您可以约束 类型参数的关联类型以符合协议。为了 例如,<S: Sequence> where S.Iterator.Element: Equatable指定S符合Sequence协议并且关联的类型S.Iterator.Element符合Equatable协议。这个约束 确保序列的每个元素都是等价的。
简单地说,where 允许您指定有关泛型参数的关联类型的约束,而在 <> 中您不能这样做。
【讨论】:
像这样的问题总是需要一些实际的例子,即使是最简单的例子来获得基本的想法。否则,它通常仍然是理论上的。
正如 Sweeper 所引用的,where 之后的内容称为类型约束。通常,您指定一个或多个协议,这些协议引入了传递的对象或类型必须满足的条件。如前所述,只有在where 之后,您才能指定泛型类型的associatedtype 约束。
考虑以下示例:
protocol MyProtocol {
associatedtype AType
func foo()
}
class MyClassInt : NSObject, MyProtocol {
typealias AType = Int
func foo() {
print(type(of: self))
}
}
class MyClassString : NSObject, MyProtocol {
typealias AType = String
func foo() {
print("I'm not implemented")
}
}
extension MyProtocol where Self.AType == Int {
func test() {
self.foo()
}
}
现在检查我们的东西:
let str = MyClassString()
str.test() // Won't compile !!
'MyClassString.AType'(又名'String')不能转换为'Int'
这个编译运行:
let int = MyClassInt()
int.test()
在这个例子中,我们有一个指定了associatedtype 的协议。还有一个extension,它只适用于我们的MyProtocol,特别是associatedtype,在我们的例子中是Int。该扩展定义了单一方法。如您所见,编译器不允许我们使用associatedtype 调用该方法,而不是由约束指定的方法,即使MyClassString 也实现了该协议。
【讨论】: