简单的
// protocol
// 搞不懂为嘛不使用Flier<T>,而要多使用一个关键字associatedtype
// 注: associatedtype是swift2.2新引入的关键字, 先前为typealias
protocol Flier {
associatedtype T
func flyWith(f: T)
func mateWith(f: T)
func shitWith(f: Self) //Self表示将要实现这个接口的那个`类`的类型
}
// 实现接口
class Bird: Flier {
func flyWith(f: String) {}
func mateWith(f: String) {}
func shitWith(f: Bird) {}
}
// 函数
func takeAndReturn<T>(t: T) -> T {
return t
}
takeAndReturn("hello")
takeANdReturn(2)
// 结构体
struct HolderOfTwoSame<T> {
var v1: T
var v2: T
}
HolderOfTwoSame(v1: "hello", v2: "world")
// 类
class Animal<T> {
func playWith(t: T) {
print("I am playing with: \(t)")
}
}
// 继承自指定了具体的泛型类型的Animal
class Dog: Animal<String> {}
// 继承自泛型的Animal
class AnotherDog<T>: Animal<T> {
override func playWith(t: T) {
print("I played with: \(t)")
}
}
var animal = Animal<Int>()
animal.playWith(2)
var d = Dog();
d.playWith("only string allowed here")
var dd = AnotherDog<String>()
dd.playWith("xiaohua")
多个泛型参数
// protocol
// 搞不懂为嘛不使用Flier<A,B>,而要多使用一个关键字associatedtype?
protocol Flier {
associatedtype A
associatedtype B
func flyWith(f: A)
func mateWith(f: B)
func shitWith(f: Self) //Self表示将要实现这个接口的那个`类`的类型
}
class Bird: Flier {
func flyWith(f: String) {}
func mateWith(f: String) {}
func shitWith(f: Bird) {}
}
// func
func takeAndReturn<A,B>(v1: A, v2: B) -> (A,B) {
return (v1, v2)
}
takeAndReturn("hello", v2: 2)
// struct
struct HolderOfTwoType<A, B> {
var v1: A
var v2: B
}
HolderOfTwoType(v1: "hello", v2: "world")
// class
class Animal<A,B> {
func playWith(t: A, and: B) {
print("I am playing with: \(t) and \(and)")
}
}
class Dog: Animal<String, Int> {}
var animal = Animal<Int, String>()
animal.playWith(2, and: "Alice")
var d = Dog();
d.playWith("only string allowed here", and: 3)
带类型约束的(protocol)
// 第一版
// protocol
protocol Flier {
func flyWith(f: Flier)
}
class Bird: Flier {
// 这里只能和protocol保持一致,声明为Flier,
// 声明为Bird就会报错, (怎么能在这里定义成Bird, 见下面)
func flyWith(f: Flier) {}
}
class ButterFly: Flier{
func flyWith(f: Flier){}
}
var b1 = Bird()
var b2 = ButterFly()
b1.flyWith(b2)
// 以下是第二版
// protocol
protocol SuperFlier {}
protocol Flier: SuperFlier {
// error: type may not reference itself as a requirement
// associatedtype T: Flier
associatedtype T: SuperFlier
// 可以用一个类型为Flier的占位符放在这里
// 但是蛋疼的是, 不能使用接口自身做为占位符
// 所以这里定义了一个什么都不干的SuperFlier以此满足compiler的要求
func flyWith(f: T)
}
class Bird: Flier {
// 然后就可以在这里使用Bird
func flyWith(f: Bird) {}
}
var b1 = Bird()
b1.flyWith(b1)
带类型约束的(func)
// 出现了Self或associatedtype关键字的protocol叫做generic protocol
// generic protocol不能直接放在参数列表中, 只能做为类型约束(出现在尖括号里)
protocol Flier {
associatedtype T
func flyWith(f: T)
}
// 注意这里的Bird并没有实现该generic protocol, 只是使用了(依赖)Flier
class Bird{
// error: protocol 'Flier' can only be used as a generic constraint because it has Self or associated type requirements
//func flyWith(f: Flier) {}
// 上面这行代码出错, 应该改为
func flyWith<T: Flier>(f: T) {}
}
// eg2: 函数体中的小于号要求这里的泛型参数必须是Comparable类型的
func myMin<T: Comparable>(things: T...) -> T {
var minimum = things[0]
for ix in 1..<things.count {
if things[ix] < minimum {
minimum = things[ix]
}
}
return minimum
}
待续
阅读[What do you really know about typealias and associatedtype?]
在实现中指定泛型类型的几种方式
// 接口如下
protocol IAnimal {
associatedtype T = Double // 其中 = Double是指定它的默认实现类型, 可以去掉
func playWith(t: T)
}
class Cat : IAnimal {
// 1. 通过typealias指定associatedtype的具体类型
typealias T = String
func playWith(t: T) {
print("I played with: \(t)")
}
}
// 2. 通过尖括号指定associatedtype的具体类型
class AnotherCat<T> : IAnimal {
func playWith(t: T) {
print("I played with: \(t)")
}
}
// 3. 通过尖括号指定associatedtype的具体类型(带类型约束)
class YetAnotherCat<T: IAnimal> : IAnimal {
func playWith(t: T) {
print("I played with: \(t)")
}
}
var cat1 = Cat()
cat1.playWith("meow")
var cat2 = AnotherCat<Int>()
cat2.playWith(2)
var cat3 = YetAnotherCat<Cat>()
cat3.playWith(cat1)
待续