美文网首页
Swift 泛型简单应用

Swift 泛型简单应用

作者: 效宇笑语 | 来源:发表于2017-01-13 11:49 被阅读0次

    泛型从字面来理解就是一种泛指的类型,通过在类、方法、接口等指定泛型的类型,可以避免重写,达到重用的目的,而且可以通过泛型限制某些变量的类型,本文通过几个例子来阐述泛型在实际应用开发中的作用,并从以下几个方面介绍:

    <h1>(1)泛型定义 </h1>

    <h1>(2)泛型方法 </h1>

    <h1>(3)泛型接口 </h1>

    <h1>(4)泛型类 </h1>

    <h2> 一、泛型定义 </h2>

    通过尖括号指定泛型类型<T>,其中的T就是将要表示的类型被称为占位符,swift的泛型可以指定任意类型,Int,String等。

    <h2> 二、泛型方法 </h2>

    下面通过一个程序来介绍泛型方法,该方法用于交换两个相同类型的值。

    1.交换两个Int类型的值

     func swapTest(inout a : Int , inout b: Int) {
        let c: Int = a
        a = b
        b = c
    }
    var a = 10
    var b = 20
    swapTest(&a, b: &b)
    

    2.交换两个String类型的值

    func swapTest(inout a : String , inout b: String) {
        let c: String = a
        a = b
        b = c
    }
    var a = "Tom"
    var b = "Jerry"
    swapTest(&a, b: &b)
    

    此时就会发现问题,当每次新增一种类型时,就需要再写一个功能相同的函数,就会出现冗余,为了解决相同功能的函数在不同类型的对象间代码公用,那么我们需要使用泛型函数:

    func swapTest<T>(inout a : T , inout b: T) {
        let c: T = a
        a = b
        b = c
    }
    var a = 10
    var b = 20
    swapTest(&a, b: &b)
    var aString = "Tom"
    var bString = "Jerry"
    swapTest(&aString , &bString)
    

    通过指定占位符来实现泛型函数,其中的T就为占位符,也就是说,函数在声明的时候并没有制定类型T,该类型需要在调用的时候指定,再看看此时函数的参数,也是通过占位符来限制a、b的类型相同。当调用函数swapTest时,函数会根据传入参数的类型确定T的实际类型。
    当然泛型的占位符可以根据需要指定多个,例如:

    func tuple<T , V>(a: T , b: V) -> (T , V) {
        let tu: (T , V) = (a , b)
        return tu
    }
    

    此方法根据指定两个泛型占位符,为调用处返回一个元胞数组。需要注意的是,此处虽然指定了两个泛型占位符,但是不代表T与V的类型一定不相同,可以进行如下调用tuple(10,20)。

    <h2> 三、泛型接口(协议)</h2>

    泛型接口与泛型方法和泛型类的定义略有不同,泛型接口在定义的时候并不直接通过尖括号声明,而是在接口内部通过associatedtype 并跟一个泛型占位符指定。如下所示

    protocol CallBack {
        associatedtype Element
        var callBack: ((callData: Element!) -> Void)? { set get }
        func load(d: Element!)
    }
    

    此时Element就是一个占位符,泛型接口与普通的接口不一样,不可以用作变量的类型,只能用于对泛型进行约束,例如说不可以存在如下代码 var c = CallBack<Person>()。实现了该接口的类在进行load后会调用callBack将数据传回调用出。

    <h2> 四、泛型类 </h2>

    泛型类的定义如下所示:

    class PrjObj: NSObject {    
         override init() {        super.init()    }   
         func test() {            }
    }
    class Test<T: PrjObj>: NSObject{
        var testObj: [T]!
        init(testObj: [T]) {
            super.init()
            self.testObj = testObj
        }
        func testObjFunc()  {
            for one in self.testObj {
                one.test()
            }
        }
    }
    

    通过声明Test类,该类的泛型占位符只接受PrjObj的子类,用于进行项目相关类的测试。只要是PrjObj的子类,就可以加入到数组中,进行测试。

    <h2> 泛型的实际应用:</h2>

    下面让我来模拟一个实际应用的场景,当网络请求成功后,将数据回调(仅仅是模拟)。
    首先需要一个回调接口

    protocol CallBack {
        associatedtype Element
        var callBack: ((callData: Element!) -> Void)? { set get }
        func load(d: Element!)
    }
    

    就像协议泛型所描述的,该协议的作用是限制实现了协议的类的功能,当位于服务层的网络请求响应成功后,会调用load方法,load方法的作用是调用callBack,将数据回溯至相关页面。

    class Implement<T>: NSObject , CallBack {
       typealias Element = T
       var data: T!
       var callBack: ((callData: T!) -> Void)?
       func load(d: T!) {
           self.data = d
           self.callBack?(callData: self.data)
       }
    }
    

    Implement类为实现了CallBack接口的泛型类,并实现了load方法,load方法将设置data值,并将调用callBack。

    class CarListener: Implement{    
        static let instance: CarListener = CarListener()
    }
    class PersonListener: Implement{
        static let instance: PersonListener = PersonListener()
    }
    

    声明两个Lisener的实现类,用来发送和接受相关类型的回调,PersonListener只负责用于Person类的回调,CarListener只负责Car类的回调

    class DispatchReceive {
        var personListener: PersonListener = PersonListener.instance
        var carListener: CarListener = CarListener.instance
        func onMessage(person: Person!) {
        }
        func onMessage(car: Car!) -> Void {
        }
        init() {
            self.personListener.callBack = onMessage 
            self.carListener.callBack = onMessage
        }
    }
    

    DispatchReceive定义PersonListener 和 CarListener具体的回调方法,当相关的数据从服务器返回,会调用各自的onMessage方法,传入不同的参数。

    class DispatchPost {
        // data from server
        func receivePersonFromServer() {
            PersonListener.instance.load(Person())
        }
        func receiveCarFromServer() {
            CarListener.instance.load(Car())
        }
    }
    

    DispatchPost 服务器返回数据,通过调用load方法将消息分发出去。

    相关文章

      网友评论

          本文标题:Swift 泛型简单应用

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