swift泛型

159 阅读3分钟

1.类型约束

  • 你可以在一个类型参数名后面放置一个类名或者协议名,并用冒号进行分隔,来定义类型约束,它们将成为类型参数列表的一部分。对泛型函数添加类型约束的基本语法如下所示(作用于泛型类型时的语法与之相同):

  • 下面展示了 findIndex(ofString:in:) 函数的泛型版本 findIndex(ofString:in:)。请注意这个函数返回值的类型仍然是 Int?,这是因为函数返回的是一个可选的索引数,而不是从数组中得到的一个可选值。需要提醒的是,这个函数无法通过编译,原因会在例子后面说明:

  • 上面所写的函数无法通过编译。问题出在相等性检查上,即 if value == valueToFind。不是所有的 Swift 类型都可以用等式符(==)进行比较。比如说,如果你创建一个自定义的类或结构体来表示一个复杂的数据模型,那么 Swift 无法猜到对于这个类或结构体而言“相等”意味着什么。

  • Swift 标准库中定义了一个 Equatable 协议,该协议要求任何遵循该协议的类型必须实现等式符(==)及不等符(!=) ,所有的 Swift 标准类型自动支持 Equatable 协议

  • findIndex(of:in:) 唯一的类型参数写做 T: Equatable,也就意味着“任何符合 Equatable 协议的类型 T

2.关联类型

  • 定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分将会非常有用。关联类型为协议中的某个类型提供了一个占位名(或者说别名),其代表的实际类型在协议被采纳时才会被指定。你可以通过 associatedtype 关键字来指定关联类型。

  • 协议没有指定容器中元素的类型,只指定了遵守协议,必须实现的方法,同时声明了associatedtypeItemType 关联类型。这个协议无法定义 ItemType 是什么类型的别名,这个信息将留给遵从协议的类型来提供

  • intStack 遵守Container 协议,需要实现协议的方法,指定关联类型的真是类型。

  • 由于swift中的类型推导,不用写typealias ItemType = Int ,省略这一句,会推导append(item:) 方法,传的是什么类型,

  • Stack 遵守Container协议,stack 是范型,具体的类型,有外部就决定 append(item:) 传入的是范型的类型:代码如下

3.范型where 语句

  • 为关联类型定义约束也是非常有用的,可以在参数列表中通过where语句,为关联类型定义约束。

  • where 使用场景

  • 可以通过where 语句,要求关联类型遵守特定的协议,以及某个参数的类型必须和关联类型的类型相同,

  • 可以通过where语句,紧跟参数列表后面来定义where语句,where子句后面跟一个或者多个针对关联类型的约束,以及一个或者多个参数类型和关联类型的相等关系。

  • 可以在函数体或类型大括号之前添加where语句

  • 例子检验2个容器是不是相同,其中元素个数,顺序,顺序上的值是否都相同?

  • 这个函数接受 someContainer 和 anotherContainer 两个参数。参数 someContainer 的类型为 C1,参数 anotherContainer 的类型为 C2。C1 和 C2 是容器的两个占位类型参数,函数被调用时才能确定它们的具体类型

  • C1 必须符合 Container 协议(写作 C1: Container)。 C2 必须符合 Container 协议(写作 C2: Container)。

  • C1 的 ItemType 必须和 C2 的 ItemType类型相同 ,C1 的 ItemType 必须符合 Equatable 协议,第三个和第四个要求被定义为一个 where 子句,写在关键字 where 后面,它们也是泛型函数类型参数列表的一部分

  • someContainer和 anotherContainer可以通过!= 操作其中的元素