Swift是一门强类型语言,而Objective-C是弱类型语言(OC是动态性语言,让程序可以在运行时判断和决定其该有的行为,所以OC属于弱类型)。所以使用时需要注意对象之间关系,用is as as? as! 这些操作符来处理对象之间关系
Swift基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式。
本篇文章学习自泊学(boxueio.com)
类型的判断 - is
- is用来判断对象是否属于某个类 或者子类,相当于OC的:isKindOf
- 示例 - 1:
class Shape {}
class Rectangle: Shape {}
class Circle: Shape {}
let r = Rectangle()
let c = Circle()
let shapeArr: Array<Shape> = [r,c]
// 统计arr中各种形状的数量 is操作符; 用 A is B 这样的用法来判断对象类型
var totalRects: Int = 0
var totalCircles:Int = 0
shapeArr[0] is Rectangle
for s in shapeArr
{
if s is Rectangle
{
// ++totalRects
totalRects += 1
}else if s is Circle{
totalCircles += 1
}
}
此时totalRects和totalCircles打印结果均为1
另外:三个月前的shapeArr.dynamicType
fix成了type(of: shapeArr)
++totalRects
修改成 totalRects += 1
类型转换 - as? as!
- 子类到父类的类型转换是自动完成的
- 从父类到子类的转换通常是需要我们明确指定的,管这样的转换叫downcasting向下转型,在swift中用as关键字来完成这个操作
- as? 和 as!:
as? 会转换成一个目标类型的optional
as!在转换成功时直接返回一个目标类型,失败的时候会引发运行时错误。所以 当转换一定会成功时才使用as!
示例 - 2:
shapeArr[0] as? Rectangle
shapeArr[0] as! Rectangle
shapeArr[0] as? Circle
// shapeArr[0] as! Circle // error
在playground可以看到 此时分别输出:
Optional<Rectangle>
Rectangle
nil
- 除了用于downcasting父类到子类这样的转换,as还可以用于AnyObject的转换。 swift中用AnyObject表示任意类型的对象
AnyObject as! Custom
示例 - 3:
// 把示例 - 1 中的shapeArr该成:
let shapeArr: Array<AnyObject> = [r,c]
此时后面的转换依然成立
5. as
① 除了as!或as? 还可以使用as自身
② 当编译器也知道一定能转成功的时候可以用as
let rect = r as Rectangle // 如果此时用as!则会警告 forced cast of 'Rectangle' to same type has no effect
③ as可以直接用在switch case语句里,可以直接把对象转换成目标类型。相当于as!
let Box: Array<Any> = [ // Any, 表示任意一种类型
3,3.14,"3.1415",r,{ return "I'm a closure" }
]
closure是一个类型,不是对象,所以用Any,不用AnyObject
for item in Box
{
switch item
{
case is Int: // ①
print("\(item) is Int")
case is Double:
print("\(item) is Double")
case is String:
print("\(item) is String")
case let rect as Rectangle: // ②
print("\(rect)")
print("\(item) is Rectangle")
case let fn as () -> String:
fn()
default:
print("out of Box")
}
}
注释:
① is 还可以判断Any和其他类型的关系,类似isKindOf
② 在case的value binding里使用as,当item的类型是Rectangle时 就会自动地把结果绑定给rect,此时编译器也知道一定能转成功,所以此处相当于as!, -> let rect = item as Rectangle
protocol 与 is as as!as?
除了转换Any和AnyObject之外,is和as还可以用来判断某个类型是否遵从protocol的约定
- 判断某个类型是否遵从了protocol的约定
把示例-1中的class Shape {}
改成:protocol Shape {}
Box[0] is Shape
此时值为false
- 使用as操作符,把对象转换成一个protocol类型
Box[3] as? Shape
type(of: (Box[3] as? Shape))
type(of: (Box[3] as! Shape))
Box[3] as! Shape
c as Shape
在playground看到,此时值分别为:
Rectangle
Optional<Shape>.Type
Rectangle.Type
Rectangle
Circle
由此可以看出:
当类型转换成功的时候,如果使用的是as!,swift会把转换结果变成对象的真实类型,而不是protocol; 而当使用as?进行类型转换时,得到的就会是一个目标类型的Optional