Swift从入门到精通第二十篇 - 不透明类型 初识
时间:2019-10-24
本文章向大家介绍Swift从入门到精通第二十篇 - 不透明类型 初识,主要包括Swift从入门到精通第二十篇 - 不透明类型 初识使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
不透明类型(Opaque Type)(学习笔记)
环境Xcode 11.0 beta4 swift 5.1
- 不透明类型可解决的问题
如下示例,打印一个图形
protocol Shape { func draw() -> String } // struct Triangle: Shape { var size: Int func draw() -> String { var result = [String]() for length in 1...size { result.append(String(repeating: "*", count: length)) } return result.joined(separator: "\n") } } let smallTriangle = Triangle(size: 3) print(smallTriangle.draw()) // * // ** // ***
可以通过上面使用泛型来翻转
struct FlippedShape<T: Shape>: Shape { var shape: T func draw() -> String { let lines = shape.draw().split(separator: "\n") return lines.reversed().joined(separator: "\n") } } let flippedTriangle = FlippedShape(shape: smallTriangle) print(flippedTriangle.draw()) // *** // ** // *
可以用上面的两个来组装一个图形
struct JoinedShape<T: Shape, U: Shape>: Shape { var top: T var bottom: U func draw() -> String { return top.draw() + "\n" + bottom.draw() } } let joinedTriangles = JoinedShape(top: smallTriangle, bottom: flippedTriangle) print(joinedTriangles.draw()) // * // ** // *** // *** // ** // * // 对于 JoinedShape、 FlippedShape 不关心使用者,模型的公共接口由这两个操作组成,然后返回一个 Shape 类型值即可
- 返回不透明类型
可以将不透明类型看作泛型的反面,以下的函数返回类型要依据调用者
func max<T>(_ x: T, _ y: T) -> Where T: Comparable { ... }
下面的示例是返回一个梯形,但没有对外暴露底层的类型
struct Square: Shape { var size: Int func draw() -> String { let line = String(repeating: "*", count: size) let result = Array<String>(repeating: line, count: size) return result.joined(separator: "\n") } } // 此函数定义返回一个 some Shape 类型 func makeTrapezoid() -> some Shape { let top = Triangle(size: 2) let middle = Square(size: 2) let bottom = FlippedShape(shape: top) let trapezoid = JoinedShape( top: top, bottom: JoinedShape(top: middle, bottom: bottom) ) return trapezoid } let trapezoid = makeTrapezoid() print(trapezoid.draw()) // * // ** // ** // ** // ** // * // 结合不透明类型返回泛型 func flip<T: Shape>(_ shape: T) -> some Shape { return FlippedShape(shape: shape) } func join<T: Shape, U: Shape>(_ top: T, _ bottom: U) -> some Shape { JoinedShape(top: top, bottom: bottom) } let opaqueJoinedTriangles = join(smallTriangle, flip(smallTriangle)) print(opaqueJoinedTriangles.draw()) // * // ** // *** // *** // ** // *
在用不透明作返回值时,所有可能的返回值必须是相同的类型,如下是错误的
func invalidFlip<T: Shape>(_ shape: T) -> some Shape { if shape is Square { return shape // Error: return types don't match } return FlippedShape(shape: shape) // Error: return types don't match } // 上面的用 Square 调用返回是 Square,其它情况返回的是 FlippedShape 类型 // 上面一种修复的方法是将 Square 的特殊情况移动到 FlippedShape 内部实现,这样就可以统一返回类型 struct FlippedShape<T: Shape>: Shape { var shape: T func draw() -> String { if shape is Square { return shape.draw() } let lines = shape.draw().split(separator: "\n") return lines.reversed().joined(separator: "\n") } }
下面是将类型参数合并到返回值的底层类型中,且在下面示例中,返回值具有相同的底层类型
[T]
,它仍然遵守了具有不透明类型函数返回的类型是单一类型的要求func `repeat`<T: Shape>(shape: T, count: Int) -> some Collection { return Array<T>(repeating: shape, count: count) }
- 不透明类型和协议类型的不同
两者非常相似,主要区别在于它们是否保留类型标识符;不透明类型指的是一种特定的类型,协议类型是可以引用作保符合协议的类型;一般来讲,协议类型在存储的值的
基础类型方面更灵活,而不透明类型使对这些基础类型做出更强的保证。以下是协议类型代替不透明类型func protoFlip<T: Shape>(_ shape: T) -> Shape { return FlippedShape(shape: shape) } // 保留灵活性,可以返回多种类型 func protoFlip<T: Shape>(_ shape: T) -> Shape { if shape is Square { return shape } return FlippedShape(shape: shape) } let protoFlippedTriangle = protoFlip(smallTriangle) let sameThing = protoFlip(smallTriangle) protoFlippedTriangle == sameThing // Error // 上面一行是错的,因为协议没有实现 == 操作符,如果实现了还是错的,因为 == 操作符需要知道左边和右边参数,而通常这种操作符会有一个默认的 Self // 与采用协议的任何具体类型匹配,但当使用协议作为类型时,给协议添加 Self 需求不准类型擦除发生 // 使用协议作为返回值增加了灵活性,但返回值的一些操作就不可用,如 == 使用协议类型作返回值无法保留特定类型信息
有关联类型的协议不能作为返回值
protocol Container { associatedtype Item var count: Int { get } subscript(i: Int) -> Item { get } } extension Array: Container { } // Error: Protocol with associated types can't be used as a return type. func makeProtocolContainer<T>(item: T) -> Container { return [item] } // // Error: Not enough information to infer C. func makeProtocolContainer<T, C: Container>(item: T) -> C { return [item] }
不透明类型作为返回类型表达式
func makeOpaqueContainer<T>(item: T) -> some Container { return [item] } let opaqueContainer = makeOpaqueContainer(item: 12) let twelve = opaqueContainer[0] print(type(of: twelve)) // Prints "Int" // 说明不透明类型和类型推断一起使用,传入12,可以推导出底层类型 [Int]
原文地址:https://www.cnblogs.com/tzsh1007/p/11642799.html
- inotify软件部署及实时同步
- Linux下批量修改文件名方法
- Tomcat启动慢解决方法(本人CentOS7.4系统)
- Nginx软件部署配置过程
- iptables网络安全服务详细使用
- 未来哪个行业能赚钱,看百度、阿里、腾讯投资的企业你就知道了!
- Augmate公司应用分布式账本技术,将IOTA整合为物联网设备管理平台
- 一域名一年前六位数终端易主 是为了......
- 黑客通过Facebook Messenger传播加密货币挖掘恶意软件
- linq to sql的多条件动态查询(下)
- iptables网络安全服务详细使用
- iptables网络安全服务详细使用
- linq to sql的多条件动态查询(上)
- 极简区块链手册:什么是区块链?什么是比特币?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法