JHHK

欢迎来到我的个人网站
行者常至 为者常成

12_02、泛型

目录

泛型使用

/// 一、泛型使用
func genericsUse() -> Void {
    
    //1、 相同逻辑不同类型 需要写两个方法
    do{
        print("--------1---------")
        var num1 = 10
        var num2 = 20
        func swapInt(_ num1:inout Int, _ num2:inout Int){
            let temp = num1
            num1 = num2
            num2 = temp
        }
        swapInt(&num1,&num2)
        print(num1,num2)
        
        func swapDouble(_ num1:inout Double,_ num2:inout Double){
            let temp = num1
            num1 = num2
            num2 = temp
        }

        var dnum1 = 10.0
        var dnum2 = 20.0
        swapDouble(&dnum1, &dnum2)
        print(dnum1,dnum2)
    }

    
    //2、解决方式一:any
    do{
        print("--------2---------")
        func swapAny(_ item1:inout Any,_ item2:inout Any){
            let temp = item1
            item1 = item2
            item2 = temp
        }

        var int1:Any = 10
        var int2:Any = 20
        swapAny(&int1, &int2)
        print(int1,int2)
        
        var float1:Any = 10.0
        var float2:Any = 20.0
        swapAny(&float1, &float2)
        print(float1,float2)
        
        var str1:Any = "hehe"
        var str2:Any = "haha"
        swapAny(&str1, &str2)
        print(str1,str2)
    }

    
    //3、解决方式二:generic 泛型
    do{
        print("--------3---------")
        func swapGeneric<T>(_ num1:inout T,_ num2:inout T){
            let temt = num1
            num1 = num2
            num2 = temt
        }
        
        var int1 = 10
        var int2 = 20
        swapGeneric(&int1, &int2)
        print(int1,int2)

        var float1 = 10.0
        var float2 = 20.0
        swapGeneric(&float1, &float2)
        print(float1,float2)

        var str1 = "hehe"
        var str2 = "haha"
        swapGeneric(&str1, &str2)
        print(str1,str2)

            
        //    let fn = swapGeneric//报错 Generic parameter 'T' could not be inferred
            let fn:(inout String,inout String)->Void = swapGeneric
            print(fn(&str1, &str2))
            
            
        //泛型可以有多个
        func test<T1, T2>(_ t1: T1, _ t2: T2) {}
        var fnt: (Int, Double) -> () = test
    }
}

泛型使用2

/// 二、泛型使用2
func genericsUse2() -> Void {
    class Stack{
        var elements = [Int]()
        func push(_ element:Int) {
            elements.append(element)
        }
        func pop() -> Int {
            elements.removeLast()
        }
        func top() -> Int {
            elements.last!
        }
        func size() ->Int {
            elements.count
        }
    }
    
    let stack = Stack()
    
    
    
    //泛型可以将类型参数化
    //提高代码复用率,减少代码量
    class Stack2<E>{
        var elements = [E]()
        func push(_ element:E) {
            elements.append(element)
        }
        func pop() -> E {
            elements.removeLast()
        }
        func top() -> E {
            elements.last!
        }
        func size() ->Int {
            elements.count
        }
    }
    
    let stack2 = Stack2<Int>()
    stack2.push(1)
    stack2.push(2)
    print(stack2.pop())
    print(stack2.top())
    print(stack2.size())
    
    
    struct Stack3<E> {
        var elements = [E]()
        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>.point(99.5)//报错
//    let score4 = Score.grade("A")//报错
    let score5 = Score<Int>.grade("A")
    print(score0,score1,score2,score5)

    
    //继承香瓜
    class SubStack<E> : Stack2<E> {}

}

关联类型使用

/// 三、关联类型使用
//关联类型的作用:给协议中用到的类型定义一个占位名称
//协议中可以拥有多个关联类型
protocol Stackable {
    associatedtype Element // 关联类型
//    associatedtype Element2 // 关联类型
    mutating func push(_ element: Element)
    mutating func pop() -> Element
    func top() -> Element
    func size() -> Int
}

protocol Runnable2 { }

protocol Stackable2 {
    associatedtype Element:Equatable
}

func accociatedTypeUse() -> Void {
    //1、给关联类型设定真实类型
    do{
        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 }
            
        }
        
        let ss = StringStack()
        ss.push("Jack")
        ss.push("Rose")
    }

    
    //2、给关联类型设定泛型
    do{
        class Stack<E> : Stackable {
            // typealias Element = E
            var elements = [E]()
            func push(_ element: E) {
                elements.append(element)
            }
            func pop() -> E { elements.removeLast() }
            func top() -> E { elements.last! }
            func size() -> Int { elements.count }
        }
    }
    
    
    
    //3、类型约束
    do{
        class Person { }
        func swapValues<T : Person & Runnable2>(_ a: inout T, _ b: inout T) {
            (a, b) = (b, a)
        }
        
        class Stack2<E : Equatable> : Stackable2 {
            typealias Element = E
        }
        
        func equal<S1: Stackable2, S2: Stackable2>(_ s1: S1, _ s2: S2) -> Bool where S1.Element == S2.Element, S1.Element : Hashable {
            return false
        }
        
        let stack1 = Stack2<Int>()
        let stack2 = Stack2<Int>()
        let stack3 = Stack2<String>()
        
        print(equal(stack1, stack2))
    //    print(equal(stack1, stack3))//报错 S1.Element == S2.Element 条件不满足 一个 Int 一个 String
    }
}

some的使用

/// 四、some的使用
protocol Runnable4 {
    associatedtype Speed
}
func someUse(){
    class Car:Runnable4{
        typealias Speed = Int
    }

    class Person:Runnable4{
        typealias Speed = Double
    }
    
    //返回一个遵守 Runable4 的类型
    //如果 Runable4 有关联类型 这么写会报错
//    func get(_ type:Int)->Runnable4{
//        if type == 0 {
//            return Car()
//        }
//        return Person()
//    }
    
    //解决方法一:泛型
    do{
        func get<T:Runnable4>(_ type:Int)->T{
            if type == 0 {
                return Car() as! T
            }
            return Person() as! T
        }
        
        
        let car:Car = get(0)
        let person:Person = get(1)
    }
    
    
    
    
    //解决方案2:使用some关键字声明一个不透明类型
    //some限制只能返回一种类型
    do{
//        func get(_ type: Int) -> some Runnable4 {
//            Car()
//        }
//        var r1 = get(0)
//        var r2 = get(1)

        
        //some除了用在返回值类型上,一般还可以用在属性类型上
//        class Dog : Runnable4 { typealias Speed = Double }
//
//        class Person {
//            var pet: some Runnable4 {
//                return Dog()
//            }
//        }
    }
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.