文章目录

  • 为类型转换定义类层次
  • 检查类型
  • 向下转型
  • Any 和 AnyObject 的类型转换

类型转换可以判断实例的类型,也可以将实例看做是其父类或者子类的实例。

类型转换在 Swift 中使用 is 和 as 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。也可以用它来检查一个类型是否实现了某个协议。

为类型转换定义类层次

可以将类型转换用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。

下面的三个代码段定义了一个类层次和一个包含了这些类实例的数组,作为类型转换的例子。

第一个代码片段定义了一个新的基类 MediaItem。这个类为任何出现在数字媒体库的媒体项提供基础功能。特别的,它声明了一个 String 类型的 name 属性,和一个 init(name:) 初始化器。

class MediaItem {var name: Stringinit(name: String) {self.name = name}
}

下一个代码段定义了 MediaItem 的两个子类。第一个子类 Movie 封装了与电影相关的额外信息,在父类的基础上增加了一个 director 属性,和相应的初始化器。第二个子类 Song,在父类的基础上增加了一个 artist属性,和相应的初始化器:

class Movie: MediaItem {var director: Stringinit(name: String, director: String) {self.director = directorsuper.init(name: name)}
}class Song: MediaItem {var artist: Stringinit(name: String, artist: String) {self.artist = artistsuper.init(name: name)}
}

最后一个代码段创建了一个数组常量 library,包含两个 Movie 实例和三个 Song 实例。library 的类型是在它被初始化时根据它数组中所包含的内容推断来的。Swift 的类型检测器推断出 Movie 和 Song 有共同的父类 MediaItem,所以推断出 [MediaItem] 类作为 library 的类型。

let library = [Movie(name: "Casablanca", director: "Michael Curtiz"),Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),Movie(name: "Citizen Kane", director: "Orson Welles"),Song(name: "The One And Only", artist: "Chesney Hawkes"),Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]

在幕后 library 里存储的媒体项依然是 Movie 和 Song 类型的。但是,若你迭代它,依次取出的实例会是 MediaItem 类型的,而不是 Movie 和 Song 类型。为了让它们作为原本的类型工作,你需要检查它们的类型或者向下转换它们到其它类型。

检查类型

用类型检查操作符( is )来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 true,否则返回 false。

下面的例子定义了两个变量,movieCount 和 songCount,用来计算数组 library 中 Movie 和 Song 类型的实例数量:

var movieCount = 0
var songCount = 0for item in library {if item is Movie {movieCount += 1} else if item is Song {songCount += 1}
}print("Media library contains \(movieCount) movies and \(songCount) songs")
// 打印 “Media library contains 2 movies and 3 songs”

向下转型

某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符( as? 或 as! )。

因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式 as? 返回一个你试图向下转成的类型的可选值。强制形式 as! 把试图向下转型和强制解包转换结果结合为一个操作。

当你不确定向下转型可以成功时,用类型转换的条件形式( as? )。条件形式的类型转换总是返回一个可选值,并且若下转是不可能的,可选值将是 nil。这使你能够检查向下转型是否成功。

只有你可以确定向下转型一定会成功时,才使用强制形式( as! )。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。

下面的例子,迭代了 library 里的每一个 MediaItem,并打印出适当的描述。为了能够在描述中使用 Movie 或 Song 的 director 或 artist 属性,item 需要真正作为 Movie 或 Song 的类型来使用,而不仅仅是作为 MediaItem。

在这个示例中,数组中的每一个 item 可能是 Movie 或 Song。事前你不知道每个 item 的真实类型,所以这里使用条件形式的类型转换( as? )去检查循环里的每次下转:

for item in library {if let movie = item as? Movie {print("Movie: '\(movie.name)', dir. \(movie.director)")} else if let song = item as? Song {print("Song: '\(song.name)', by \(song.artist)")}
}// Movie: Casablanca, dir. Michael Curtiz
// Song: Blue Suede Shoes, by Elvis Presley
// Movie: Citizen Kane, dir. Orson Welles
// Song: The One And Only, by Chesney Hawkes
// Song: Never Gonna Give You Up, by Rick Astley

注意:转换没有真的改变实例或它的值,根本的实例保持不变,只是简单地把它作为它被转换成的类型来使用。

Any 和 AnyObject 的类型转换

Swift 为不确定类型提供了两种特殊的类型别名:

Any 可以表示任何类型,包括函数类型。
AnyObject 可以表示任何类类型的实例。

只有当你确实需要它们的行为和功能时才使用 Any 和 AnyObject。在你的代码里使用你期望的明确类型总是更好的

这里有个示例,使用 Any 类型来和混合的不同类型一起工作,包括函数类型和非类类型。它创建了一个可以存储 Any 类型的数组 things:

var things = [Any]()
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" })

things 数组包含两个 Int 值,两个 Double 值,一个 String 值,一个元组 (Double, Double),一个Movie实例“Ghostbusters”,以及一个接受 String 值并返回另一个 String 值的闭包表达式。可以在 switch 表达式的 case 中使用 is 和 as 操作符来找出只知道是 Any 或 AnyObject 类型的常量或变量的具体类型。

下面的示例迭代 things 数组中的每一项,并用 switch 语句查找每一项的类型。有几个 switch 语句的 case 绑定它们匹配到的值到一个指定类型的常量,从而可以打印这些值:

for thing in things {switch thing {case 0 as Int:print("zero as an Int")case 0 as Double:print("zero as a Double")case let someInt as Int:print("an integer value of \(someInt)")case let someDouble as Double where someDouble > 0:print("a positive double value of \(someDouble)")case is Double:print("some other double value that I don't want to print")case let someString as String:print("a string value of \"\(someString)\"")case let (x, y) as (Double, Double):print("an (x, y) point at \(x), \(y)")case let movie as Movie:print("a movie called '\(movie.name)', dir. \(movie.director)")case let stringConverter as (String) -> String:print(stringConverter("Michael"))default:print("something else")}
}// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called Ghostbusters, dir. Ivan Reitman
// Hello, Michael

注意:
Any 类型可以表示所有类型的值,包括可选类型。Swift 会在你用 Any 类型来表示一个可选值的时候,给你一个警告。如果你确实想使用 Any 类型来承载可选值,你可以使用 as 操作符显式转换为 Any。

例如:
let optionalNumber: Int? = 3
things.append(optionalNumber) // 警告 “Expression implicitly coerced from ‘Int?’ to ‘Any’”
things.append(optionalNumber as Any) // 没有警告

Swift learning part 18 - 类型转换相关推荐

  1. swift 对象转换_Swift类型转换–照原样,任何对象

    swift 对象转换 In this tutorial, we'll be looking into the details of Swift Type Casting. Let's get star ...

  2. Swift learning part 20 - 扩展

    文章目录 扩展的语法 计算型属性 构造器 方法 可变实例方法 下标 嵌套类型 扩展可以为一个已有的类.结构体.枚举或者协议添加新功能.它还具有在不访问被扩展类型的原始源代码的情况下完成扩展的能力(即 ...

  3. 【Machine Learning】18.Softmax函数

    Softmax函数 1.导入 2.Softmax函数 2.1 算法简介 2.2 损失函数 3.Tensorflow 3.1 The *Obvious* organization 3.2 preferr ...

  4. 《Swift 权威指南》——导读

    本节书摘来自异步社区<Swift 权威指南>一书中的目录,作者 李宁,更多章节内容可以访问云栖社区"异步社区"公众号查看 目 录 内容提要 前言 第1章 未来的iOS开 ...

  5. 2个字符串相等 swift_Swift快速入门(一)之 Swift基础语法

    Swift快速入门(一)之 Swift基础语法 近期重新学习了一遍Swift语言,主要以<Swift编程权威指南(第2版)>为教程,学习过程中结合比对Java语言特性将学习心得作为三篇笔记 ...

  6. Machine Learning课程 by Andrew Ng

    大名鼎鼎的机器学习大牛Andrew Ng的Machine Learning课程,在此mark一下: 一:Coursera: https://www.coursera.org/learn/machine ...

  7. ios swift版 sqlite3详解

    iOS中的SQLite3的封装与详细应用 SQLite是一个开源的嵌入式关系数据库,特点是易使用.高效.安全可靠.可移植性强. iOS中的本地持久化存储 NSUserDefault:一般用于存储小规模 ...

  8. 【论文总结】Prototype Rectification for Few-Shot Learning(附翻译)

    Prototype Rectification for Few-Shot Learning 小样本学习的原型校正 论文地址:https://arxiv.org/pdf/1911.10713v1.pdf ...

  9. Day 5. Suicidal Ideation Detection: A Review of Machine Learning Methods and Applications综述

    Title: Suicidal Ideation Detection: A Review of Machine Learning Methods and Applications 自杀意念检测:机器学 ...

  10. 论文《Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts》

    论文地址:https://dl.acm.org/doi/pdf/10.1145/3219819.3220007 摘要 常用的多任务学习往往对于任务之间的关系比较敏感,论文提出的MMoE将专家混合结构应 ...

最新文章

  1. Spring Boot Admin 2.0开箱体验
  2. html两方框重叠透明,html – 边缘浏览器向透明div添加重叠的“边缘”
  3. vc得到屏幕的当前分辨率方法
  4. php通知websocket,php实现websocket实时消息推送
  5. swift面向对象之方法
  6. Touch事件分发源码解析
  7. for in和for of的区别(转)
  8. cam350菜单怎么切换成中文_对CAM350英文菜单不熟悉的可以参考一下这份CAM350中文菜单...
  9. python随机抽号_Python学习随记 ————随机抽号器(一)
  10. IDEA学生授权申请方式(免费)
  11. linux marvell 网卡驱动,如何在linux下安装MarvellYukon网卡驱动?
  12. HTML5 音频文件
  13. trove 基本介绍
  14. android 键盘将底部视图顶起,android 弹出软键盘将底部视图顶起问题
  15. Spring Boot 2.0 配置图文教程 1
  16. 十只老鼠在1000瓶药水中找一瓶有毒的
  17. 红米note4x开启root权限
  18. python(scikit-learn)实现k均值聚类算法
  19. 甲骨文称:IT安全投得多不如投得巧
  20. python调用htk工具箱_语音识别工具箱之HTK安装与使用

热门文章

  1. 怎么压缩PPT大小?
  2. java decompiler 乱码_jd-gui-1.6.6 乱码问题整理(about jd-gui-1.6.6 garbled code.)
  3. 软路由硬件, 研究了一圈还是J1900 , i211网卡又如何
  4. 打开matlab窗口,不小心关闭了matlab的命令窗口怎么再打开?谢谢,十分急
  5. 腾讯cdn设置 php,WordPress使用腾讯云CDN配置教程(https)
  6. 【word】复制到word的文字不能调整行间距(行间距过大)
  7. word流程图怎么使箭头对齐_word怎么将图形对齐
  8. MATLAB导入数据
  9. 大庆金桥:基于 SpreadJS 开发实现计量器具检定证书的在线生成与打印
  10. 阿里云服务器系列(一)安装Java与Jenkins