Swift泛型Protocol对比C#泛型Interface
本篇纯属抬杠之作,之前我们提到了Swift的泛型Protocol使用associatedtype关键字,而不是使用<Type>语法的泛型参数。这其中有什么好处呢?
我就这个问题搜索了一些回答,大体上提到两点:
<Type>语法对Protocol没有意义,Protocol仅需要定义一个抽象的概念,具体的类型应该由实现的Class来明确,比如:
ClassWithInt<Int>: NumberProtocol ClassWithDouble<Double>: NumberProtocol
associatedtype可以用来给Protocol中特定Func添加泛型约束,而不是限定整个Protocol
protocol GeneratorType {associatedtype Elementpublic mutating func next() -> Self.Element? }
听上去还是有一定道理的,然后实践是检验事实的唯一标准。下面我们通过代码实例来和C#进行对比。首先拿出网上多被引用解释上述两个观点的Swift代码:
public protocol Automobile {associatedtype FuelTypeassociatedtype ExhaustTypefunc drive(fuel: FuelType) -> ExhaustType } public protocol Fuel {associatedtype ExhaustTypefunc consume() -> ExhaustType } public protocol Exhaust {init()func emit() }public struct UnleadedGasoline<E: Exhaust>: Fuel {public func consume() -> E {print("...consuming unleaded gas...")return E()} } public struct CleanExhaust: Exhaust {public init() {}public func emit() {print("...this is some clean exhaust...")} } public class Car<F: Fuel,E: Exhaust>: Automobile where F.ExhaustType == E {public func drive(fuel: F) -> E {return fuel.consume()} }public class Car1<F: Fuel>: Automobile {public func drive(fuel: F) -> F.ExhaustType {return fuel.consume()} }
具体的使用情况如下:
var car = Car<UnleadedGasoline<CleanExhaust>, CleanExhaust>() car.drive(fuel: UnleadedGasoline<CleanExhaust>()).emit()var fusion = Car1<UnleadedGasoline<CleanExhaust>>() fusion.drive(fuel: UnleadedGasoline<CleanExhaust>()).emit()
转换成C#代码的话,有两种思路,首先是把泛型参数放到Interface层面:
public interface Automobile<FuelType, ExhaustType>{ExhaustType Drive(FuelType fuel);}public interface Fuel<ExhaustType>{ExhaustType consume();}public interface Exhaust {void Emit();}public class UnleadedGasoline<Exhaust> : Fuel<Exhaust> where Exhaust : new(){public Exhaust consume(){Console.WriteLine("...consuming unleaded gas...");return new Exhaust();}}public class CleanExhaust : Exhaust{public void Emit(){Console.WriteLine("...this is some clean exhaust...");}}public class Car : Automobile<UnleadedGasoline<CleanExhaust>, CleanExhaust>{public CleanExhaust Drive(UnleadedGasoline<CleanExhaust> fuel){return fuel.consume();}}
还可以模仿Swift对Automobile多做一层继承进行包装:
public interface Car1<T1> : Automobile<UnleadedGasoline<T1>, T1> where T1 : new(){}public class SimpleCar : Car1<CleanExhaust>{public CleanExhaust Drive(UnleadedGasoline<CleanExhaust> fuel){return fuel.consume();}}
调用的时候没有什么太大的差别:
var gaso = new UnleadedGasoline<CleanExhaust>(); var car = new Car();car.Drive(gaso).Emit(); var simpleCar = new SimpleCar();simpleCar.Drive(gaso).Emit();
和Swift比较不同的是,我们在Interface就代入了泛型参数。但是由于我们不能直接实例化Interface,所以并不能直接使用Automobile来减少一层继承关系。
因为上述提到的使用associatedtype 的第一点理由见仁见智,这里不分高下。
C#还有第二种思路,就是我也把泛型约束下放到Func层级:
public interface Automobile{ExhaustType Drive<FuelType,ExhaustType>(FuelType fuel) where ExhaustType : new();}public interface Fuel{ExhaustType consume<ExhaustType>() where ExhaustType : new();}public class UnleadedGasoline : Fuel{public Exhaust consume<Exhaust>() where Exhaust : new(){Console.WriteLine("...consuming unleaded gas...");return new Exhaust();}}public class Car2 : Automobile{public CleanExhaust Drive<UnleadedGasoline, CleanExhaust>(UnleadedGasoline fuel) where CleanExhaust : new(){return (fuel as Fuel).consume<CleanExhaust>();}}
C#的接口并不能定义构造函数。强行模仿起来还真是有点累啊。最终的使用也很简单:
var fuel = new UnleadedGasoline();var car2 = new Car2();car2.Drive<UnleadedGasoline,CleanExhaust>(fuel).Emit();
通篇比较下来,应该说Swift通过associatedtype 关键字和<Type>的混用,使得泛型的定义更为复杂也更灵活了。
GitHub:
https://github.com/manupstairs/LearnSwift
https://github.com/manupstairs/LearnDotNetCore
转载于:https://www.cnblogs.com/manupstairs/p/5980850.html
Swift泛型Protocol对比C#泛型Interface相关推荐
- java 接口的泛型方法_Java泛型/泛型方法/通配符/泛型接口/泛型泛型擦出
从JDK1.5以后引入了三大常用新特性:泛型.枚举(enum).注解(Annotation).其中JDK1.5中泛型是一件非常重要的实现技术,它可以帮助我们解决程序的参数转换问题.本文为大家详细介绍一 ...
- Java:高级之泛型概念引入,泛型可以设置多个类型参数,泛型继承和泛型接口实现,限制泛型可用类型,泛型通配的方式,泛型方法,泛型方法限制泛型可用类型
目录页 泛型简介 泛型类 限制泛型可用类型 类型通配声明 泛型方法 问题引入 如果我们需要产生多个对象,每个对象的逻辑完 ...
- java 泛型集合应用_Java泛型集合的应用和方法
展开全部 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以62616964757a686964616fe78988e69d8331333 ...
- Java泛型(1)--集合使用泛型Generic、自定义泛型、泛型在继承上的体现、通配符的使用
文章目录 泛型的概念 集合中使用泛型 自定义泛型结构 泛型在继承上的体现 通配符的使用 泛型的概念 集合容器类在设计阶段/声明阶段不能确定这个容器实际存的是什么类型的对象,所以在JDK1.5之前只能把 ...
- java泛型与接口_Java泛型用于方法,类和接口
什么是泛型? 型就是数据类型参数化.就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了.使用的时候再确定就可以了. 泛型的特点 是JDK1 ...
- java 反射和泛型-反射来获取泛型信息
通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public.获得Field对象后都可以使用getType()来获取其类型. Class&l ...
- java 怎么为泛型参数赋值_Java泛型讲解
1. 概述在引入泛型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型 就可以在细分成更多的类型. 例如原先的类型List,现在在细分成List, List等 ...
- java基本数据类型泛型_Java中的泛型
泛型规范在JDK1.5版本中被添加,使用泛型机制编写的代码比起随意使用Object变量然后再进行强制类型转换的代码具有更高的安全性和可读性,同时也更为简洁.泛型对于集合类尤其有用,例如 ArrayLi ...
- .net java 泛型_Java高级特性泛型看这一篇就够了
作者:qwer1030274531 出自:ITPUB博客 1.为什么我们需要泛型? 通过两段代码就可以知道为什么需要泛型 /*** * 没有泛型的时候实现加法 */public class NonGe ...
最新文章
- 由mysql分区想到的分表分库的方案
- 如何将S/4HANA系统存储的图片文件用Java程序保存到本地
- lambda 延迟执行_Java Lambdas和低延迟
- BitAdminCore框架更新日志20180529
- df python 增加数据_美国确诊超100万!教你用Python画出全球疫情动态图(附数据下载)...
- 指针变量的声明、地址相关运算--“*”和“”
- 【STM32F429的DSP教程】第14章 DSP统计函数-最大值,最小值,平均值和功率
- 平面设计配色方案有哪些
- CorelDRAW2023安装下载教程精简版矢量绘图软件
- 暗黑2符文之语大全_暗黑破坏神2符文之语一览,附符文镶嵌顺序和底材
- 查询出每一个雇员的姓名,工资,部门名称,工资在公司的等级及其领导的姓名,领导的工资,以及领导所相应的等级...
- java贪吃蛇代码idea_IntelliJ idea使用笔记 - 贪吃蛇学院-专业IT技术平台
- 日历 java 代码
- ArchSummit讲师专访:EMC研究院资深研究员陶隽谈实时数据分析
- 信息系统集成解决医院系统
- ISP算法----基本DPC算法实现代码
- 【5G之道】第六章:下行链路物理层处理
- linux软件实现看门狗,一个软件实现的Linux看门狗—soft_wdt
- 远程桌面连接软件轻松实现远程移动办公
- 在冷风中我凌乱了半小时,只因健康码刷不出来
热门文章
- Asp.Net中using的使用的方法(转)
- 如今的移动操作系统,写在2013年——android篇 by 伊一线天
- 6大主流开源SQL引擎总结,遥遥领先的是谁?
- linux下搭建FTP服务器
- linux系统在虚拟机中迁移的技术难点
- i++与++i的区别,使用实例说明
- 使用@Order调整配置类加载顺序
- MySQL中的information_schema
- python中other_Python other
- git push到GitHub的时候遇到! [rejected] master -> master (non-fast-forward)的问题