- 泛型可以将类型参数化,提高代码复用率,减少代码量
var n1 = 10
var n2 = 20
func swapValues<T>(_ a:inout T,_ b:inout T){
(a,b) = (b,a)
}
swapValues(&n1,&n2)
print(n1,n2)
- 泛型函数赋值给变量
func test<T1,T2>(_ t1:T1,_ t2:T2){}
var fn:(Int,Int) ->() = test
泛型类型
class Stack<E> {
var elements = [E]()
init(firstElement:E){
elements.append(firstElement)
}
func push(_ element:E){elements.append(element)}
func pop() ->E {elements.removeLast()}
func top() ->E {elements.last!}
func size() ->Int {elements.count}
}
var instack = Stack<Int>()
var stringStack = Stack<String>()
var anyStack = Stack<Any>()
//var stack = Stack<Double>(firstElement:10)
class SubStack<E>:Stack<E> {}
struct Stack<E> {
var elements = [E]()
init(firstElement:E){
elements.append(firstElement)
}
mutating func push(_ element:E){elements.append(element)}
mutating func pop() ->E {elements.removeLast()}
func top() ->E {elements.last!}
func size() ->Int {elements.count}
}
enum Score<T> {
case point(T)
case grade(String)
}
let score0 = Score<Int>.point(100)
let score1 = Score.point(99)
let score2 = Score.point(99.5)
let score3 = Score<Int>.grade("A")
关联类型(Associated Type)
- 关联类型的作用:给协议中用到的类型定义一个占位名称
- 协议中可以拥有多个关联类型
protocol Stackable {
associatedtype Element // 关联类型
mutating func push(_ element:Element)
mutating func pop() -> Element
func top() ->Element
func size() ->Int
}
class StringStack : Stackable {
// 给关联类型设定真实类型
// typealias Element = String
var elements = [String]()
func push(_ element:String){elements.append(element)}
func pop() ->String {elements.removeLast()}
func top() ->String {elements.last!}
func size() -> Int {elements.count}
}
var ss = StringStack()
ss.push("Jack")
ss.push("Rose")
class Stack<E>:Stackable {
var elements = [E]()
func push(_ element:E){
elements.append(element)
}
func pop ->E {elements.removeLase()}
func top -> E {elements.last!}
func size() -> Int{elements.count}
}
类型约束
protocol Runnable {}
class Person {}
func swapValues<T:Person & Runnable>(_ a:inout T,_ b:inout T){
(a,b) = (b,a)
}
protocol Stackable {
associatedtype Element:Equatable
}
class Stack<E:Equatable>:Stackable{
typealias Element = E
}
func equal<S1:Stackable,S2:Stackable>(_ s1:S1,_ s2:S2) -> Bool
where S1.Element == S2.Element,S1.Element:Hashable
{
return false
}
var s1 = Stack<Int>()
var s2 = Stack<Int>()
var s3 = Stack<String>()
equal(s1,s2)
协议类型的注意点
protocol Runnable {}
class Person:Runnable{}
class Car:Runnable{}
func get(_ type:Int) -> Runnable {
if type == 0 {
return Person()
}
return Car()
}
var r1 = get0) // person
var r2 = get(1) // car
如果协议中有associatedtype,
protocol Runnable{
associatedtype Speed // 关联类型
var speed:Speed{get}
}
class Person : Runnable {
var speed : Double{0.0}
}
class Car : Runnable {
var speed :Int {0}
}
func get(_ type: Int) - >Runnable {
if type == 0 {
return Person()
}
return Car()
}
var r1 = get(0)
var r2 = get(1)
解决办法
func get<T:Runnable>(_ type: Int) ->T {
if type == 0 {
return Person() as! T
}
return Car() as! T
}
var r1:Person = get(0)
var r2:Car = get(1)
不透明类型(Opaque Type)
- 解决方案2:使用some关键字声明一个不透明类型,不想外界知道真实类型
- some只能返回一种类型
func get(_ type: Int) -> some Runnable {
return Car()
}
some
- some除了用在返回值类型上,一般还可以用在属性类型上
protocol Runnable{
associatedtype Speed // 关联类型
}
class Dog : Runnable {
typealias Speed = Double
}
class Person {
var pet : some Runnable {
return Dog()
}
}
可选项的本质
- 可选项的本质是enum类型
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
public init(_ some: Wrapped)
}
var age:Int? = 10
var age0:Optional<Int> = Optional<Int>.some(10)
var age1:Optional = .some(10)
var age2 = Optional.some(10)
var age3 = Optional(10)
age = nil
age = .none
var age:Int? = nil
var age0 = Optional<Int>.none
var age1:Optional<Int> = .none
var age:Int? = .none
age = 10
age = .some(20)
age = nil
swtich age {
case let v?:print("some",v)
case nil:print("none")
}
swtich age {
case let .some(v):print("some",v)
case .none:print("none")
}
var age = 10
switch age {
case let a where a > 20
print(a)
case 20:print(1)
default:break
}
case let a // 如果写成这样是可选项绑定,是不会走到下面去判断,在swtich里面是不会解包