is和as
类型转换 可以判断实例的类型,也可以将实例看做是其父类或者子类的实例。
类型转换在 Swift 中使用 is
和 as
操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。
直接上代码,首先定义几个类:
//类型的检査与转换
class Fruit{
let placeOfOriginal: String
init(placeOfOriginal: String){
self.placeOfOriginal = placeOfOriginal
}
}
class Apple:Fruit{
func desCription(){
print("苹果的原产地\(placeOfOriginal)")
}
}
class Orange:Fruit{
func desCription(){
print("橘子的原产地\(placeOfOriginal)")
}
}
func testOne(){
//定义了五个水果
let apple1 = Apple(placeOfOriginal: "北京")
let apple2 = Apple(placeOfOriginal: "上海")
let apple3 = Apple(placeOfOriginal: "深圳")
let orange1 = Orange(placeOfOriginal: "成都")
let orange2 = Orange(placeOfOriginal: "广州")
let basket = [apple1,apple2,apple3,orange1,orange2]
for fruit in basket{
//1:如果想要使用子类Apple和Orange的方法那么久必须使用 as操作符进行类型转换,转换为对应的类型.
if let apple = fruit as? Apple{
apple.desCription()
}else if let orange = fruit as? Orange{
orange.desCription()
}
}
//如果我们想知道篮子里有多少苹果有多少橘子,所以恶魔需要使用is操作符,来挨个检测这些水果类实例,到底是苹果还是橘子.
var appleCount = 0
var orangeCount = 0
for fruit in basket{
//1:如果想要使用子类Apple和Orange的方法那么久必须使用 as操作符进行类型转换,转换为对应的类型.
if fruit is Apple{
appleCount++
}else if fruit is Orange{
orangeCount++
}
}
print("水果篮子里有:\(appleCount)个苹果和\(orangeCount)个橘子")
//水果篮子里有:3个苹果和2个橘子
}
总结 is和as的用法
:
is操作符是一个类型检査操作符,在Swift中,对它的定义是:检测一个实例是不是特定类的子类型,如果是,则该操作符返回true,如果不是,则返回false.在使用is操作符时,需要注意:is操作符的左操作数只能是一个父类的实例,而右操作符只能是一个子类类型,不满足该规则的代码会导致编译错误.
比如:用一个Apple的实例apple1,去看它是不是一个Orange实例,或者使用 apple1实例看是不是Apple的实例:
as操作符是一个类型转换操作符,主要用于实例在子类和父类间的转换.它有两个版本,分别是带问号的版本(as?)和不带问号的版本(as),我们把它们分别称为"as的可选格式"和"as的强制解封格式".其中 as的可选格式返回一个子类的可选类型,成功时该可选类型的值为子类实例,失败时该可选类型的值为nil.而as的强制解封格式则会强制执行转换操作,如果失败将会导致运行时错误,这里需要注意:
1:如果你不是确定你的类型转换是否成功,务必使用as?(as的可选格式),然后通过nil判断来检査成功与否.
2:如果你非常确定这个转换一定成功,就使用 as(as的强制解封格式),但要明白使用as的强制解封格式是需要承担代价的.
在使用 as操作符时,需要注意可选格式和强制解封格式在使用上的差别,其中 as?操作符严格要求坐操作数只能够为严格父类型的实例,而右操作数只能是为严格子类型,而 as操作符的限制缺相对要宽松.
AnyObject和Any
Swift为不确定类型提供了两种特殊类型别名:
AnyObject可以代表任何class类型(即类类型)的实例。
Any可以表示任何类型,包括方法类型(function types)。用来修饰任意类型的实例,包括AnyObject修饰的实例.
注意:
只有当你明确的需要它的行为和功能时才使用Any和AnyObject。在你的代码里使用你期望的明确的类型总是更好的.
AnyObject类型
//AnyObject任意实例类型
class Evil{
var name = ""
}
class Angel{
var name = ""
}
class Folk{
var name = ""
}
func testTwo(){
var hiter = Evil()
hiter.name = "希特勒"
var chenGuanBiao = Angel()
chenGuanBiao.name = "陈光标"
var laoMa = Folk()
laoMa.name = "老码"
var buddhism = [String:AnyObject]()
buddhism = ["悟空":hiter, "悟静": chenGuanBiao, "悟能":laoMa]
for (key, value) in buddhism{
if let v = value as? Evil{
print("恶魔:\(v.name) 法号:\(key)")
}else if let v = value as? Angel{
print("天使:\(v.name) 法号:\(key)")
}else if let v = value as? Folk{
print("农民:\(v.name) 法号:\(key)")
}else{
print("众生平等,不问背景!")
}
}
/*
天使:陈光标 法号:悟静
恶魔:希特勒 法号:悟空
农民:老码 法号:悟能
对于佛门我们用名为buddhism的字典,其类型为[String:AnyObject].也就是说佛门谁都可以进,不管你是恶人希特勒还是好人表格还是农民,这些都没有统一的父子类关系,但是都可以放到佛门这个字典里,因为它的类型是AnyObject,但是key是String类型,因为进入佛门的人都要一个法号.比如老码就是悟能.
在访问字典里的元素的时候,需要分别处理,因为AnyObject没有办法具体到哪个实例.
*/
}
Any类型
func testThree(){
//Any 其实Any是AnyObject的总类,完全覆盖AnyObject.
var things = [Any]()
func getSalarySummary(month: Int) -> Double{
return Double(month * 1000)
}
things.append(0)
things.append(0.0)
things.append(50)
things.append(4.1527)
things.append("hello jack")
things.append((3.0,6.0))
things.append(getSalarySummary)
for thing in things{
switch thing{
case 0 as Int:
print("这是一个整形!")
case 0 as Double:
print("0是一个Double类型!")
case let someInt as Int:
print("\(someInt) 是一个整形!")
case let someDouble as Double where someDouble > 0:
print("\(someDouble)是一个正数!")
case is Double:
print("其他Double型!")
case let someString as String:
print("字符串\(someString)型")
case let (x,y) as (Double, Double):
print("坐标(x,y)是\(x),\(y)")
case let getSalarySummaryFunction as Int -> Double:
print("总收入为: \(getSalarySummaryFunction(12))")
default:
print("其他值!")
}
}
/*
这是一个整形!
0是一个Double类型!
50 是一个整形!
4.1527是一个正数!
字符串hello jack型
坐标(x,y)是3.0,6.0
总收入为: 12000.0
注意:
在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。
*/
}