使用或不使用' where'之间的区别是什么?带有泛型的子句?

时间:2017-10-18 12:18:08

标签: swift generics

这两种声明泛型超类的方法之间的区别是什么?有'其中'条款?

func foo<T: SomeClass>(object: T) -> Array<T>

func foo<T>(object: T) -> Array<T> where T: SomeClass

2 个答案:

答案 0 :(得分:7)

Swift guide

中明确说明了这一点
  

泛型where子句中的要求指定了一个类型   参数继承自类或符合协议或协议   组成。虽然泛型where子句提供了句法   用于表达类型参数的简单约束的糖(用于   例如,<T: Comparable>相当于<T> where T: Comparable和   等等),您可以使用它来提供更复杂的类型约束   参数及其相关类型。例如,你可以约束   符合协议的相关类型参数类型。对于   例如,<S: Sequence> where S.Iterator.Element: Equatable指定   S符合Sequence协议以及相关类型   S.Iterator.Element符合Equatable协议。这个约束   确保序列中的每个元素都是等同的。

简单地说,where允许您指定关于通用参数的关联类型的约束,而在<>中则无法执行此操作。

答案 1 :(得分:1)

这些问题总是需要一些实际的例子,即使是最简单的基本想法。否则它通常仍然是理论上的。

由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以外的<link rel="stylesheet" href="Untitled-2.css" type="tex/css">来调用该方法。