加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Swift4.2语言规范(二十) 类型转换

发布时间:2020-12-14 05:11:30 所属栏目:百科 来源:网络整理
导读:类型转换 是一种检查实例类型的方法,或者将该实例视为与其自己的类层次结构中的其他位置不同的超类或子类。 Swift中的类型转换是使用 is 和 as 运算符 实现的 。 这两个运算符提供了一种简单而富有表现力的方法来检查值的类型或将值转换为其他类型。 您还可

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

Swift中的类型转换是使用isas运算符实现的这两个运算符提供了一种简单而富有表现力的方法来检查值的类型或将值转换为其他类型。

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

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

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

第一个片段定义了一个名为的新基类MediaItem此类为数字媒体库中显示的任何类型的项目提供基本功能。具体来说,它声明了一个name类型属性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 
 9 class Song: MediaItem {
10     var artist: String
11     init(name: String,artist: String) {
12         self.artist = artist
13         super.init(name: name)
14     }
15 }

最后一个片段创建一个名为的常量数组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仍然MovieSong幕后的情况。但是,如果迭代此数组的内容,则您收到的项目将被键入MediaItem,而不是MovieSong要将它们作为本机类型使用,您需要检查其类型,或将它们向下转换为其他类型,如下所述。

类型检查

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

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

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

此示例遍历library数组中的所有项在每次传递时,for-?in循环将item常量设置MediaItem为数组中的下一个

item?is?Movietrue如果当前MediaItemMovie实例,false返回如果不是返回同样,检查项目是否为实例。在结束-?循环,值含有多少的计数情况下,发现每一种类型的。item?is?SongSongforinmovieCountsongCountMediaItem

向下转型

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

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

as?当您不确定向下转换是否成功时,请使用类型转换运算符(as?的条件形式这种形式的运算符将始终返回一个可选值,nil如果无法进行向下转换,则该值将为这使您可以检查成功的向下转发。

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

下面在每个迭代的例子MediaItemlibrary,并打印每个项目的相应说明。要做到这一点,它需要访问每个项目为真,Movie或者Song不仅仅是作为一个MediaItem这是为了必要为它是能够访问directorartist的属性MovieSong在说明中使用。

在此示例中,数组中的每个项可能是a?Movie,或者它可能是a?Song您事先并不知道每个项目使用哪个实际类,因此使用类型as?转换运算符(as?的条件形式来检查每次循环时的向下转换是合适的:

?

该示例首先尝试将当前向下转换itemMovie因为item是一个MediaItem例子,这是可能的,它可能是一个Movie;?同样,它也可能是一个Song,甚至只是一

 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 
 9 // Movie: Casablanca,dir. Michael Curtiz
10 // Song: Blue Suede Shoes,by Elvis Presley
11 // Movie: Citizen Kane,dir. Orson Welles
12 // Song: The One And Only,by Chesney Hawkes
13 // Song: Never Gonna Give You Up,by Rick Astley

个基础MediaItem由于这种不确定性,as?类型转换运算符形式在尝试向下转换为子类类型时返回一个可选值。结果是类型或“可选”。item?as??MovieMovie?Movie

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

“尝试访问itemMovie如果成功,则设置一个新的临时常量,调用movie存储在返回的可选中的值Movie。“

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

注意

转换实际上不会修改实例或更改其值。基础实例保持不变;?它被简单地处理和访问,作为它的类型的实例。

非特定类型

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

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

使用AnyAnyObject只有当你明确需要的行为以及它们提供的功能。最好具体了解您希望在代码中使用的类型。

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

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

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

要发现特定类型的只是已知类型的固定或可变的Any或者AnyObject,你可以使用一个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 
26 // zero as an Int
27 // zero as a Double
28 // an integer value of 42
29 // a positive double value of 3.14159
30 // a string value of "hello"
31 // an (x,y) point at 3.0,5.0
32 // a movie called Ghostbusters,dir. Ivan Reitman
33 // Hello,Michael

注意

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

1 let optionalNumber: Int? = 3
2 things.append(optionalNumber)        // Warning
3 things.append(optionalNumber as Any) // No warning

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读