They said "you should learn a new language every year," so I  learned Swift. Now  I  learn a new language every two weeks!

  这个笑话绝对是我看过的Swift被黑的最惨的一次!所以今天我们来学习一下Swift的泛型。

  Swift的泛型有点奇怪,针对Class和Function,都是通过<Type>来定义,和C#一摸一样,同样也有where关键字进行约束。

func swapTwoValues<T>(inout a: T, inout _ b: T) {
let temporaryA = a
a = b
b = temporaryA
} class CanPrintBase<T> {
    func PrintType(output: T) -> Void {}
}

  但是面对Interface,也就是Swift里的Protocol,需要使用associatedtype关键字来定义泛型:

protocol CanPrint {
    
    associatedtype E
    
    func PrintType(output: E) -> Void
}

  那要怎么去实现这个接口呢?通常是这样子的:

class TypePrinter0 : CanPrint{
    
    typealias E = String
    
    func PrintType(output: E) {
        print(type(of:output))
    }
} let print0 = TypePrinter0()
print0.PrintType(output: "String Type")

  然后就会在output窗口打印“String”。

  阿西吧!这么奇怪的语法简直不能忍!就不能用<Type>来写吗?

  曲线救国的话,我们可以考虑模拟一个抽象类class CanPrintBase<T>,通过继承来实现同样的效果:

class TypePrinter3: CanPrintBase<String>{
    
    override func PrintType(output: String){
         print(type(of:output))
    }
} let print3 = TypePrinter3()
print3.PrintType(output: "String Type")

  那么我们像C#一样直接在类定义的时候通过占位符的方式可以嘛?

//This one cannot work!
class TypePrinter1<E: String> : CanPrint{
   
    func PrintType(output: E) {
        print(output)
    }
}

  错误提示为:Inheritance from non-protocol, non-class type 'String'。也就是说如果是class类型的话就可以:

public class SomeType {}

class TypePrinter2<E: SomeType> : CanPrint{

    func PrintType(output: E) {
        print(output)
    } } let print2 = TypePrinter2()
print2.PrintType(output: SomeType())

  反之我们也可以写成这样:

class TypePrinter5 : CanPrint{
    
    typealias E = SomeType
    
    func PrintType(output: E) {
        print(output)
    }
} let print5 = TypePrinter5();
print(type(of: print5))
print(type(of: print2))

  将类型打印出来的话,分别是TypePrinter5和TypePrinter2<SomeType>,也就是说这两种写法得到的类型是完全不一样的。

  呵呵也是蛮妖的嘛,还可以把类型的具体定义留到使用时再声明:

class TypePrinter4<E> : CanPrint{
    
    func PrintType(output: E) {
        print(output)
    }
}
let print4 = TypePrinter4<SomeType>()
print4.PrintType(output: SomeType()) let print6 = TypePrinter4<String>()
print6.PrintType(output: "I am a String")

  这一点又和C#傻傻分不清楚了。

  本篇实在是蛮无聊的纠缠与Swift泛型协议的语法,如孔乙己般尝试了回字的N种写法。至于为什么Swift要这么设计,我们下一篇可以尝试和C#对比看看。

  GitHub:

  https://github.com/manupstairs/LearnSwift/tree/master/GenericProtocolTest

Swift泛型协议的N种用法的更多相关文章

  1. swift闭包的另一种用法

    这不是教程. 当你碰到函数参数需要传递一个闭包(closure)时,一般是可以直接这么传递的(假定无返回): // 教程一般教你在参数位置传递closure: someMethod(arg1, arg ...

  2. swift 当协议遇见了泛型

    由于泛型比较简单,并没有单独拿出来介绍!我们在定义函数的时候,有时候只是由于参数或者返回值类型不同,而具体的实现过程是一模一样的,这个时候我们就可以定义泛型函数而使可以传入不同的参数类型: func ...

  3. iOS -Swift 3.0 -for(循环语句用法)

    // // ViewController.swift // Swift-循环语句 // // Created by luorende on 16/12/08. // Copyright © 2016年 ...

  4. .NET(c#)new关键字的三种用法

    前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...

  5. (转载)OC学习篇之---协议的概念和用法

    在前一篇文章中我们介绍了OC中类的延展,这一篇文章我们在来看一下OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Jav ...

  6. NEW关键字的三种用法

    最近面试中有一道题是写new关键字的几种用法,想了下写下我知道的两种用法 第一种 创建对象.调用构造函数,这就不用讲了 ClassA  A=new ClassA(); 第二种 是作为修饰符,显示隐藏继 ...

  7. OC中协议的概念以及用法

    OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Java中的接口(抽象类),只不过OC中的名字更形象点,因为我们在学习 ...

  8. c# new关键字的三种用法

    三种用法如下: 在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数. 2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成 ...

  9. Linux下dmesg命令处理故障和收集系统信息的7种用法

    目录: <syslog之一:Linux syslog日志系统详解> <syslog之二:syslog协议及rsyslog服务全解析> <syslog之三:建立Window ...

随机推荐

  1. Redis 队列操作

    class Program { //版本2:使用Redis的客户端管理器(对象池) public static IRedisClientsManager redisClientManager = ne ...

  2. (转)解释一下SQLSERVER事务日志记录

    本文转载自桦仔的博客http://www.cnblogs.com/lyhabc/archive/2013/07/16/3194220.html 解释一下SQLSERVER事务日志记录 大家知道在完整恢 ...

  3. Java实现敏感词过滤

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

  4. [安卓] 18、一个简单的例子做自定义动画按钮和自定义Actionbar

    在做安卓UI的时候有时候需自定义具有动画效果的按钮或需要自定义一下actionbar~ 本节用一个简单的demo讲如何自定义具有动画效果的按钮,以及个性化的actionbar 下面是效果: 其中: △ ...

  5. ReactMix框架,让你实现一套js代码,基于ReactNative在H5,App都能完美跑起来,Write Once,Run Anywhere

    ReactNative框架推出已经有一段时间了,相信很多小伙伴都在尝试实现Write Once, Run Anywhere的梦想,比如淘宝的ReactWeb等等,但是这些框架都局限于因为ReactNa ...

  6. SiteMesh3整合SpringMVC+FreeMarker

    SiteMesh3配置 添加maven依赖 添加filter 配置servlet 添加sitemesh配置文件 decorator示例 SpringMVC.FreeMarker配置(404问题处理) ...

  7. webservice5

    如何访问webservice . 三种方式我知道, 但是, 方式1 只说明了如何访问wsdl, 不知道如何调用,现在就是需要知道如何像下面url描述一样 , http get .post 方式调用ws ...

  8. Hibernate中对象的三个状态解析

    Hibernate 将操作的对象分为三种状态: 1. 瞬时 (Transient )/临时状态/自由状态 持久 (Persistent) 脱管 (Detached) 瞬时对象特征: 第一.不处于 Se ...

  9. Oracle函数脚本记录

    --内置函数 --聚合函数 返回单个值 '; --count()记录条数 select sum(degree) from score t; --sum(degree)求成绩总和 select avg( ...

  10. Fiddler实战深入研究(二)

    Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...