2019独角兽企业重金招聘Python工程师标准>>>
简单的
// protocol
// 搞不懂为嘛不使用Flier<T>,而要多使用一个关键字associatedtype
// 注: associatedtype是swift2.2新引入的关键字, 先前为typealias
protocol Flier {associatedtype Tfunc 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: Tvar 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 Aassociatedtype Bfunc 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: Avar 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: Flierassociatedtype T: SuperFlier// 可以用一个类型为Flier的占位符放在这里// 但是蛋疼的是, 不能使用接口自身做为占位符// 所以这里定义了一个什么都不干的SuperFlier以此满足compiler的要求func flyWith(f: T)}class Bird: Flier {// 然后就可以在这里使用Birdfunc flyWith(f: Bird) {}
}var b1 = Bird()
b1.flyWith(b1)
带类型约束的(func)
// 出现了Self或associatedtype关键字的protocol叫做generic protocol
// generic protocol不能直接放在参数列表中, 只能做为类型约束(出现在尖括号里)
protocol Flier {associatedtype Tfunc 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 = Stringfunc 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)
待续