Swift泛型协议的N种用法
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种用法的更多相关文章
- swift闭包的另一种用法
这不是教程. 当你碰到函数参数需要传递一个闭包(closure)时,一般是可以直接这么传递的(假定无返回): // 教程一般教你在参数位置传递closure: someMethod(arg1, arg ...
- swift 当协议遇见了泛型
由于泛型比较简单,并没有单独拿出来介绍!我们在定义函数的时候,有时候只是由于参数或者返回值类型不同,而具体的实现过程是一模一样的,这个时候我们就可以定义泛型函数而使可以传入不同的参数类型: func ...
- iOS -Swift 3.0 -for(循环语句用法)
// // ViewController.swift // Swift-循环语句 // // Created by luorende on 16/12/08. // Copyright © 2016年 ...
- .NET(c#)new关键字的三种用法
前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...
- (转载)OC学习篇之---协议的概念和用法
在前一篇文章中我们介绍了OC中类的延展,这一篇文章我们在来看一下OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Jav ...
- NEW关键字的三种用法
最近面试中有一道题是写new关键字的几种用法,想了下写下我知道的两种用法 第一种 创建对象.调用构造函数,这就不用讲了 ClassA A=new ClassA(); 第二种 是作为修饰符,显示隐藏继 ...
- OC中协议的概念以及用法
OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Java中的接口(抽象类),只不过OC中的名字更形象点,因为我们在学习 ...
- c# new关键字的三种用法
三种用法如下: 在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数. 2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成 ...
- Linux下dmesg命令处理故障和收集系统信息的7种用法
目录: <syslog之一:Linux syslog日志系统详解> <syslog之二:syslog协议及rsyslog服务全解析> <syslog之三:建立Window ...
随机推荐
- Restful.Data,现招募有为骚年,群号 338570336
光阴似箭,日月如梭,套用小学作文惯用的一句开场白来开始重新开始我的博客园生涯吧. 8年的风霜雪雨,不断的击打着我内心的哀伤,可我依旧坚挺的屹立在这里,是因为技术是我一直坚持的梦想. 追寻着先辈和高人的 ...
- Java设计模式7:适配器模式
适配器模式 适配器模式说的是,可以把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类可以一起工作. 适配器模式的用途 适配器模式的用途,在网上找了一幅图,挺形象 ...
- 【读书笔记】javascript 继承
在JavaScript中继承不像C#那么直接,C#中子类继承父类之后马上获得了父类的属性和方法,但JavaScript需要分步进行. 让Brid 继承 Animal,并扩展自己fly的方法. func ...
- java gc的考察
参考http://www.cnblogs.com/mazj611/p/3481610.html 看了很多博客.书, 仍然有所不懂.很多看过即忘记.实在要不得. 我们可以通过jstat获取gc情况 js ...
- svn import-纳入版本控制
转svn import-纳入版本控制 import: 将未纳入版本控制的文件或目录树提交到版本库.用法: import [PATH] URL 递归地提交 PATH 的副本至 URL. 如果省略 PA ...
- 我心中的核心组件(可插拔的AOP)~第四回 异常拦截器
回到目录 之前说过有关拦截器的文章,第二回 缓存拦截器,事实上,在那讲里说的最多是AOP和缓存组件,对于拦截的概念并没有详细的说明,这一讲,不说AOP,主要说一下拦截器,拦截器Interceptio ...
- Oracle Redo 以及 Archived日志简述
Oracle通过Redo Archived实现数据的归档 什么是Redo日志 Redo日志记录了数据的变更,用于在数据库出现故障后,进行数据恢复. 功能主要由三个组件实现:Redo Log Buffe ...
- Java构造函数
构造函数的定义: 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个 ...
- Atitit 数据存储的数据表连接attilax总结
Atitit 数据存储的数据表连接attilax总结 1.1. 三种物理连接运算符:嵌套循环连接.合并连接以及哈希连接1 1.2. a.嵌套循环连接(nested loops join)1 1.3. ...
- Atitit 理解Monad attilax总结
Atitit 理解Monad attilax总结 但函数式编程最大的一个问题是,函数是一个数学抽象,在现实世界中不存在,1 那既然这样就够用了,还要 Monad 干嘛?Monad 的作用在这里就体现出 ...