zoukankan      html  css  js  c++  java
  • Swift5.3 语言指南(二十) 类型转换

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/9739734.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    类型转换是一种检查实例类型或将该实例视为与其自身类层次结构中其他位置不同的超类或子类的方法。

    Swift中的类型转换通过isand as运算符实现。这两个运算符提供了一种简单而富有表现力的方式来检查值的类型或将值转换为其他类型。

    您还可以使用类型强制转换来检查类型是否符合协议,如检查协议一致性中所述

    定义类型转换的类层次结构

    您可以将类型转换与类和子类的层次结构一起使用,以检查特定类实例的类型,并将该实例转换为相同层次结构中的另一个类。下面的三个代码段定义了类的层次结构和包含这些类的实例的数组,以供类型转换示例使用。

    第一个代码段定义了一个名为的新基类MediaItem此类为出现在数字媒体库中的任何项目提供基本功能。具体来说,它声明一个nametype属性String和一个初始化器。(假定所有媒体项目(包括所有电影和歌曲)都将具有名称。)init name

    1. class MediaItem {
    2. var name: String
    3. init(name: String) {
    4. self.name = name
    5. }
    6. }

    下一个代码段定义的两个子类MediaItem第一个子类Movie封装有关电影或电影的其他信息。director在基MediaItem类的顶部添加一个属性,并带有一个相应的初始化程序。第二个子类,在基类的顶部Song添加一个artist属性和初始化程序:

    1. class Movie: MediaItem {
    2. var director: String
    3. init(name: String, director: String) {
    4. self.director = director
    5. super.init(name: name)
    6. }
    7. }
    8. class Song: MediaItem {
    9. var artist: String
    10. init(name: String, artist: String) {
    11. self.artist = artist
    12. super.init(name: name)
    13. }
    14. }

    最后的代码段创建一个名为的常量数组library,其中包含两个Movie实例和三个Song实例。library通过使用数组文字的内容对其进行初始化来推断数组的类型Swift的类型检查器能够推导该类型MovieSong具有的公共超类MediaItem,因此可以[MediaItem]library数组推断类型

    1. let library = [
    2. Movie(name: "Casablanca", director: "Michael Curtiz"),
    3. Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
    4. Movie(name: "Citizen Kane", director: "Orson Welles"),
    5. Song(name: "The One And Only", artist: "Chesney Hawkes"),
    6. Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
    7. ]
    8. // the type of "library" is inferred to be [MediaItem]

    存储在其中的项目library仍然是静止的,Movie并且是Song后台的实例。但是,如果您遍历此数组的内容,则返回的项将键入为MediaItem,而不是MovieSong为了使用它们作为其本机类型,您需要检查它们的类型,或将它们向下转换为其他类型,如下所述。

    检查类型

    使用类型检查运算符is)检查实例是否属于某个子类类型。类型检查运算符将返回true实例是否属于该子类类型,false如果不是。

    下面的例子定义两个变量,movieCount并且songCount,其计数的数量MovieSong实例中library阵列:

    1. var movieCount = 0
    2. var songCount = 0
    3. for item in library {
    4. if item is Movie {
    5. movieCount += 1
    6. } else if item is Song {
    7. songCount += 1
    8. }
    9. }
    10. print("Media library contains (movieCount) movies and (songCount) songs")
    11. // Prints "Media library contains 2 movies and 3 songs"

    本示例遍历library数组中的所有项目每次循环时forin循环将item常量设置MediaItem为数组中的下一个常量

    item is Movietrue如果当前MediaItemMovie实例,false返回如果不是返回同样,检查项目是否为实例。循环的末尾,的值包含找到每种类型的实例数的计数item is SongSongforinmovieCountsongCountMediaItem

    下垂

    某个类类型的常量或变量实际上可能是指幕后子类的实例。如果您认为是这种情况,可以尝试使用类型转换运算符as?as!将其转换为子类类型

    由于向下转换可能会失败,因此类型转换运算符采用两种不同的形式。条件格式会as?返回您要向下转换的类型的可选值。强制形式as!尝试向下转换并强制将结果作为单个复合动作展开。

    as?当您不确定向下转换是否成功时,请使用类型转换运算符(的条件形式这种形式的运算符将始终返回一个可选值,该值将在nil无法向下转换的情况下返回。这使您能够检查下调是否成功。

    as!仅当您确定向下转换将始终成功时,才使用类型转换运算符(的强制形式如果您尝试向下转换为不正确的类类型,则此形式的运算符将触发运行时错误。

    下面的示例对中的每个MediaItem进行迭代library,并为每个项目打印适当的描述。为此,它需要将每个项目作为true Movie访问Song,而不仅仅是访问a MediaItem为了使它能够访问directorartist属性MovieSong在说明书中使用,这是必需的。

    在此示例中,数组中的每个项目可能是Movie,也可能是Song您事先不知道要为每个项目使用哪个实际类,因此as?每次通过循环使用类型强制转换运算符(的条件形式检查向下转换是适当的:

    1. for item in library {
    2. if let movie = item as? Movie {
    3. print("Movie: (movie.name), dir. (movie.director)")
    4. } else if let song = item as? Song {
    5. print("Song: (song.name), by (song.artist)")
    6. }
    7. }
    8. // Movie: Casablanca, dir. Michael Curtiz
    9. // Song: Blue Suede Shoes, by Elvis Presley
    10. // Movie: Citizen Kane, dir. Orson Welles
    11. // Song: The One And Only, by Chesney Hawkes
    12. // Song: Never Gonna Give You Up, by Rick Astley

    该示例首先尝试将当前值向下转换itemMovie因为itemMediaItem实例,所以可能Movie同样,它也可能是一个Song,甚至仅仅是一个base MediaItem由于存在这种不确定性,当尝试向下转换为子类类型时,类型转换as?运算符形式将返回一个可选值。的结果为类型,或“可选”。item as? MovieMovie?Movie

    Movie当应用于Song库数组中实例时,向下转换失败为了解决这个问题,上面的示例使用可选绑定来检查该可选对象是否Movie实际包含一个值(即,找出向下转换是否成功。)此可选绑定被写为“ ”,可以表示为:if let movie item as? Movie

    “尝试访问itemMovie如果成功,则将一个新的临时常数设置为movie存储在返回的optional中的值Movie。”

    如果向下转换成功,movie则使用的属性来打印该Movie实例的描述,包括其名称director使用类似的原理检查Song实例,并在库中找到artista时打印适当的描述(包括名称)Song

    注意

    投射实际上不会修改实例或更改其值。基础实例保持不变;简单地将其视为已强制转换为其类型的实例并进行访问。

    类型转换为Any和AnyObject

    Swift提供两种特殊类型来处理非特定类型:

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

    使用AnyAnyObject只有当你明确需要的行为和能力,他们提供的。最好对要在代码中使用的类型进行具体说明。

    这是一个Any用于混合使用不同类型(包括函数类型和非类类型)的示例该示例创建一个名为的数组things,该数组可以存储type的值Any

    1. var things = [Any]()
    2. things.append(0)
    3. things.append(0.0)
    4. things.append(42)
    5. things.append(3.14159)
    6. things.append("hello")
    7. things.append((3.0, 5.0))
    8. things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
    9. things.append({ (name: String) -> String in "Hello, (name)" })

    things数组包含两个Int值,两个Double值,一个String值,一个类型的元组,电影“ Ghostbusters”,以及一个带一个值并返回另一个的闭包表达式(Double, Double)StringString

    地发现,仅已知类型的固定或可变的特定类型AnyAnyObject,你可以使用一个isas一个模式switch语句的情况。下面的示例遍历things数组中的项目,并使用switch语句查询每个项目的类型switch语句的几种情况将它们的匹配值绑定到指定类型的常量,以使其值能够被打印:

    1. for thing in things {
    2. switch thing {
    3. case 0 as Int:
    4. print("zero as an Int")
    5. case 0 as Double:
    6. print("zero as a Double")
    7. case let someInt as Int:
    8. print("an integer value of (someInt)")
    9. case let someDouble as Double where someDouble > 0:
    10. print("a positive double value of (someDouble)")
    11. case is Double:
    12. print("some other double value that I don't want to print")
    13. case let someString as String:
    14. print("a string value of "(someString)"")
    15. case let (x, y) as (Double, Double):
    16. print("an (x, y) point at (x), (y)")
    17. case let movie as Movie:
    18. print("a movie called (movie.name), dir. (movie.director)")
    19. case let stringConverter as (String) -> String:
    20. print(stringConverter("Michael"))
    21. default:
    22. print("something else")
    23. }
    24. }
    25. // zero as an Int
    26. // zero as a Double
    27. // an integer value of 42
    28. // a positive double value of 3.14159
    29. // a string value of "hello"
    30. // an (x, y) point at 3.0, 5.0
    31. // a movie called Ghostbusters, dir. Ivan Reitman
    32. // Hello, Michael

    注意

    Any类型表示任何类型的值,包括可选类型。如果您在Any期望使用类型值的情况下使用可选值,则Swift会警告您如果确实需要使用可选值作为Any值,则可以使用as运算符将可选值显式转换为Any,如下所示。

    1. let optionalNumber: Int? = 3
    2. things.append(optionalNumber) // Warning
    3. things.append(optionalNumber as Any) // No warning
  • 相关阅读:
    liunx基本命令
    liunx—awk
    python—__name__
    python—url路径拼接/编码
    python—__init__作用
    单元测试
    2、选择排序
    1、算法简介
    在命令行输入python出现“Warning:This Python interpreter is in a conda environment, but the environment has not been activated. Libraries may fail to load. To activate this environment please see https://conda.
    如何明确区分代码中的1和l
  • 原文地址:https://www.cnblogs.com/strengthen/p/9739734.html
Copyright © 2011-2022 走看看