swift类型检查_Type Casting

分享到:

类型转换是一种检查实例类型和/或处理该实例的方法,类似于其自身类层次中某处的一个不同的父类或子类。

通过is 和as 操作符实现Swift内的类型转换。这两个操作符提供了一个简单易懂的方法来检查值的类型或将值转换为不同的类型。

同时,还可以使用类型转换来检查某一类型是否符合协议-见检查协议一致性下的介绍。

 

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

 

可以使用具有类层次和子类层次的类型转换来检查具体类实例的类型并在同一层次上将该实例转换为另一个类。以下三个代码片段定义了类层次和阵列,其中含有这些类的实例,以便在类型转换示例中使用。

第一个代码段定义了一个新的基类MediaItem。这个类针对数字媒体库中出现的任何种类的项提供了基本功能。具体地说,它声明了一个String型name属性和一个init name初始化函数。(假定包括全部电影和音乐在内的所有媒体项目均有名称。)

 

class MediaItem {

var name: String

init(name: String) {

self.name = name

}

}

 

以下代码断定义了MediaItem的两个子类。第一个子类-Movie-将其他有关电影或影片的信息进行了概述。它在基本MediaItem类顶部添加了一个director属性,并配有相应的初始化函数。第二个子类-Song-在基本类顶部添加了一个artist属性和初始化函数:

 

class Movie: MediaItem {

var director: String

init(name: String, director: String) {

self.director = director

super.init(name: name)

}

}

class Song: MediaItem {

var artist: String

(name: String, artist: String) {

self.artist = artist

super.init(name: name)

 

最后的片段创建了一个常量阵列library,其中含有两个Movie实例和三个Song实例。利用阵列常值的内容将library阵列初始化,以此来推断出该阵列的类型。Swift类型检查器可做出以下推论:Move和Song具有MedaItem的通用超类;因此,推断出适用于library阵列的MediaItem [ ]类型:

 

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")

]

// the type of "library" is inferred to be MediaItem[]

 

存储于中的项仍然为后台的Move和Song实例。但是,如果对此阵列的内容进行迭代,则所收回的项目为MediaItem类型,而非Move或Song类型。为了使用其本机类型进行操作,需要检查其类型或将其向下转换为另一不同类型-见下文介绍。

 

检查类型

 

使用类型检查操作符检查某实例是否为特定子类类型。如果实例为特定子类类型,则类型检查操作符返回真;否则,返回假。

以下示例定义了两个变量—movecount和songCount,它们计算library阵列中Movie和Song实例的数量。

 

var movieCount = 0

var songCount = 0

for item in library {

if item is Movie {

++movieCount

} else if item is Song {

++songCount

}

("Media library contains \(movieCount) movies and \(songCount) songs")

prints "Media library contains 2 movies and 3 songs"

 

本示例演示了迭代阵列内所有项。每次传递中,for-in循环将item常量设为阵列中的下一个MedaItem。

如果当前MediaItem为Movie实例,则Movie项返回真;否则,返回假。同样,项s Song可检查此项是否为Song实例。在for-in循环的末尾,movecount和songCount的值包含所找出的各类MedaItem实例总数。

向下转换

 

特定类类型的常量或变量可能实际引用后台的子类实例。当确定出现这种情况时,可尝试采用类型转换操作符(as)向下转换为子类类型。

因为向下转换失败,类型转换运算符分为两种不同的形式。可选形式-as?-返回一个类型(需要向下转换为此类型)的可选值。

强制形式-as-试图进行向下转换,并强制将结果作为一个单一的复合动作展开。

当不确定向下转换是否会成功时,应使用类型转换操作符(as?)的可选形式。使用这个形式的操作符将始终返回可选值,并且如果不能实现向下转换,则该值将为ni。可以使你检查是否已成功完成了向下转换。

当确定向下转换总是会成功时,应使用类型转换操作符(as)的强制形式。如果试图向下转换为一个错误的类类型,则使用这个形式的操作符将触发运行时错误。

以下示例对library中的各MediaItem进行迭代,并为每项打印出适当的描述。为此,它需要作为true Movie或Song而不仅是MediaItem来访问各项。这十分必要,这样,它即可访问用于描述的Movie或Song中的director或artist属性。

在本示例中,阵列中的每一项均可以为Movie或Song。由于事先并不知道各项使用的实际类,因此,宜始终使用类型转换操作符(as?)的可选形式,每次通过循环对向下转换进行检查:

 

for item in library {

if let movie = item as? Movie {

println("Movie: '\(movie.name)', dir. \(movie.director)")

} else if let song = item as? Song {

println("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

 

本示例首先尝试把当前项向下转换为Movie。由于item为MediaItem实例,因此,它有可能是Movie;同样地,也有可能是Song,或只是基本MedaItem。由于这种不确定性,当试图向下转换为一个子类类型时,类型转换操作符的as?形式返回一个可选值。Movie项的结果为Movie?或“可选Movie”类型。

当应用library阵列中的两个Song实例时,向下转换为Movie失败。为解决这个问题,以上示例使用可选绑定来检查可选Movie是否确实包含一个值(即确认向下转换是否成功)。可选绑定编写为“if let move = item as?”可以被理解为:

“尝试访问Movie项。如果成功,将新增临时常量movie设为所返回的可选Movie中存储的值。

如果向下转化成功,则将movie属性用于打印该Movie实例的描述,包括director名称。当在library中发现Song时,用同样的原则检查Song实例,并打印出相应的描述(包括artist名称)。

注:实际上,类型转环并未修改实例或改变实例值。底层实例仍相同;它只是作为一个实例被处理和访问,该实例的类型为其转换的目标类型。

Any和AnyObject之间的类型转换

 

Swift为采用非特定类型提供了两种特殊的类型别名:

AnyObject 能够代表任何类型的一个实例

除了函数类型,Any 能够代表任何类型的一个实例。

注:仅当明确需要Any和AnyObject提供的特性和能力时,才使用Any和AnyObject。应尽量明确你希望在代码中采用的类型。

 

AnyObject

 

采用Cocoa APIs时,经常会收到AnyObject []类型的阵列或“任何对象类型值的阵列”。这是因为Objective-C中没有明确地类型数组。但是,通常只根据所掌握的该阵列有关API的信息,即可信任该阵列中包含的对象类型。

在这些情况下,可使用强制类型转换操作符(as)将阵列中的各项向下转换,使之变为比AnyObject更具体的类类型,无需可选展开。

以下示例定义了AnyObject []类型的阵列,并将此阵列与三个Movie类实例一起进行了概述:

 

let someObjects: AnyObject[] = [

Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),

Movie(name: "Moon", director: "Duncan Jones"),

Movie(name: "Alien", director: "Ridley Scott")

]

 

由于已知此阵列仅包含Movie实例,因此,可使用强制类型转换操作符(as)直接向下转换并展开为非可选Movie:

 

for object in someObjects {

let movie = object as Movie

println("Movie: '\(movie.name)', dir. \(movie.director)")

}

// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick

// Movie: 'Moon', dir. Duncan Jones

// Movie: 'Alien', dir. Ridley Scott

 

对于此循环的较短形式,将someObjects阵列向下转换为Movie []类型,而不是将所有项均向下转换:

 

for movie in someObjects as Movie[] {

println("Movie: '\(movie.name)', dir. \(movie.director)")

}

// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick

// Movie: 'Moon', dir. Duncan Jones

 // Movie: 'Alien', dir. Ridley Scott

 

在以下示例中,将Any与不同类型(包括非类类型)的组合一同使用。本示例创建一个阵列things,可以存储类型为Any的数值:

 

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阵列包含两个Int值、两个Double值、一个String值、一个类型元组(Doube、Doube)和伊万·瑞特曼导演的电影《捉鬼敢死队》。

可以使用语句中的is和as操作符来找出常量和变量的具体类型,此类型仅已知为Any或AnyObject的类型。以下示例对things阵列中的项进行了迭代,并使用语句查询了各项的类型。语句的几个将其匹配值绑定成一个具有指定类型的常量,以使其值可被打印。

 

for thing in things {

switch thing {

case 0 as Int:

println("zero as an Int")

case 0 as Double:

println("zero as a Double")

case let someInt as Int:

println("an integer value of \(someInt)")

case let someDouble as Double where someDouble > 0:

println("a positive double value of \(someDouble)")

case is Double:

println("some other double value that I don't want to print")

case let someString as String:

println("a string value of \"\(someString)\"")

case let (x, y) as (Double, Double):

println("an (x, y) point at \(x), \(y)")

case let movie as Movie:

println("a movie called '\(movie.name)', dir. \(movie.director)")

fault:

println("something else")

 

zero as an Int

zero as a Double

an integer value of 42

positive double value of 3.14159

string value of "hello"

an (x, y) point at 3.0, 5.0

movie called 'Ghostbusters', dir. Ivan Reitman

 

注:语句的使用强制类型转换操作符(as,as?)来检查并转换为某特定类型。为安全起见,通常在switch case语句上下文中进行检查。

昵    称:
验证码:

相关文档:

swift
IOS实例
ObjectiveC