美文网首页
泛型(Generics)

泛型(Generics)

作者: 曹来东 | 来源:发表于2019-07-17 18:02 被阅读0次
  • 泛型可以将类型参数化,提高代码服用率,减少代码
func swapValues<T>(_ a: inout T,_ b: inout T) {
    (a,b) = (b,a)
}
var i1 = 10
var i2 = 20
print(i1)
print(i2)
swap(&i1, &i2)
print(i1)
print(i2)
struct Date {
    var year = 0,month = 0,day = 0
}
var dd1 = Date(year: 2011, month: 2, day: 3)
var dd2 = Date(year: 2012, month: 10, day: 12)
print(dd1)
print(dd2)
swapValues(&dd1, &dd2)
print(dd1)
print(dd2)
//打印结果
10
20
20
10
Date(year: 2011, month: 2, day: 3)
Date(year: 2012, month: 10, day: 12)
Date(year: 2012, month: 10, day: 12)
Date(year: 2011, month: 2, day: 3)
  • 类实现栈结构
class Stack<E> {
    var elements = [E]()
    func push(_ element: E) {
        elements.append(element)
    }
    func pop() -> E {
       return elements.removeLast()
    }
    func top() -> E {
       return elements.last!
    }
    func size() -> Int {
        return elements.count
    }
}
var stack = Stack<Int>()
stack.push(11)
stack.push(22)
stack.push(33)
print(stack.top())//33
print(stack.pop())//33
print(stack.pop())//22
print(stack.size())//1

class SubStack<E> : Stack<E> {

}
  • 结构体实现栈结构
struct Stack<E> {
    var elements = [E]()
    mutating func push(_ element: E) {
        elements.append(element)
    }
    mutating func pop(_ element: E) {
        elements.removeLast()
    }
    func top() -> E {
        return elements.last!
    }
    func size() -> Int {
        return 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(90.2)
let score3 = Score<String>.grade("A")

关联类型(Associated Type)

  • 关联类型的作用: 给协议中用到的类型定义一个占位名称
  • 协议中可以拥有多个关联类型
protocol Stackable {
    associatedtype Element //关联类型
    mutating func push(_ element: Element)
    mutating func pop() -> Element
    func top() -> Element
    func size() -> Int
}
class Stack<E>: Stackable {
    typealias Element = E
    var elements = [E]()
    func push(_ element: Stack<E>.Element) {
        elements.append(element)
    }
    func pop() -> Stack<E>.Element {
        return elements.removeLast()
    }
    func top() -> Stack<E>.Element {
        return elements.last!
    }
    func size() -> Int {
        return elements.count
    }
}
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 {
        return elements.removeLast()
    }
    func top() -> String {
        return elements.last!
    }
    func size() -> Int {
        return elements.count
    }
    
}
var ss = StringStack()
ss.push("Jack")
ss.push("Rose")
print(ss.pop())//Rose 不是e

类型约束

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 = <#type#>
 
}

func equal<S1: Stackable,S2: Stackable>(_ s1: S1,_ s2: S2) -> Bool
    where S1.Element == S2.Element,S1.Element : Hashable{
        return false
}

var stact1 = Stack<Int>()
var stack2 = Stack<String>()

equal(stact1, stack2)

协议作为返回值类型

protocol Runnable { }
class Person: Runnable {}
class Car: Runnable { }
func get(_ type: Int) -> Runnable {
    if type == 0 {
        return Person()
    }
    return Car()
}
var r1 = get(0)
var r2 = get(1)


protocol Runnable {
    associatedtype Speed
    var speed: Speed { get }
    
}
class Person: Runnable {
    var speed: Double { return 0.0 }
}
class Car: Runnable {
    var speed: Int { return 0 }
}

  • 如果协议中有associatedtype或者使用了Self作参数会报错
    image.png
  • 方案一: 使用泛型
protocol Runnable {
    associatedtype Speed
    var speed: Speed { get }
    
}
class Person: Runnable {
    var speed: Double { return 0.0 }
}
class Car: Runnable {
    var speed: Int { return 0 }
}

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)
  • 方案2: 使用some关键字(Opaque Type, 不透明类型)
protocol Runnable {
//    associatedtype Speed
//    var speed: Speed { get }
    
}
class Person: Runnable {
   // var speed: Double { return 0.0 }
}
class Car: Runnable {
    //var speed: Int { return 0 }
}

func get(_ type: Int) -> some Runnable {
    Car()
}
  • some限制只能返回一种类型.下面代码报错
protocol Runnable {
//    associatedtype Speed
//    var speed: Speed { get }
    
}
class Person: Runnable {
   // var speed: Double { return 0.0 }
}
class Car: Runnable {
    //var speed: Int { return 0 }
}

func get(_ type: Int) -> some Runnable {
    if type == 0 {
        return Person()
    }
    return Car()
}

可选项的本质

  • 可选项的本质是enum类型
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)
    public init(_ some: Wrapped)
}
var age: Int? = .none
age = 10
age = .some(20)
age = nil
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
age3 = .none
var age: Int? = nil
var age0 = Optional<Int>.none
var age1: Optional<Int> = .none
var age: Int? = nil
var age0 = Optional<Int>.none
var age1: Optional<Int> = .none

switch age {
case let v?:
    print("some",v)
case nil:
    print("none")
}

switch age {
case let .some(v):
    print("some",v)
case .none:
    print("none")
}

var age_: Int? = 10
var age: Int?? = age_
age_ = nil
var age0 = Optional.some(Optional.some(10))
age0 = .none
var age1: Optional<Optional> = .some(.some(10))

var age: Int?? = 10
var age0: Optional<Optional> = 10

相关文章

网友评论

      本文标题:泛型(Generics)

      本文链接:https://www.haomeiwen.com/subject/sefclctx.html