Swift 中的类型转换(Type Casting)用于在继承层次结构中检查和转换实例的类型,主要用于:
检查对象是否属于某个类或协议
将父类引用转换为子类(向下转型)
处理 Any / AnyObject 容器
安全地调用特定类型的方法
一、核心关键字
关键字
用途
is
类型检查,返回 Bool
as?
可选转换(failable),返回 Optional
as!
强制转换(force unwrap),失败时崩溃
as
向上转型(upcast),100% 安全
二、基础示例
class Animal {
func makeSound() { print("...") }
}
class Dog: Animal {
func bark() { print("Woof!") }
}
class Cat: Animal {
func meow() { print("Meow!") }
}
// 多态数组
let pets: [Animal] = [Dog(), Cat(), Dog()]
// 1. 类型检查(is)
for pet in pets {
if pet is Dog {
print("这是一只狗")
} else if pet is Cat {
print("这是一只猫")
}
}
// 2. 可选转换(as?)
for pet in pets {
if let dog = pet as? Dog {
dog.bark() // 安全调用
} else if let cat = pet as? Cat {
cat.meow()
}
}
三、as vs as? vs as!
写法
说明
安全
适用场景
as
向上转型(子 → 父)
100% 安全
Dog() as Animal
as?
可选向下转型
安全
运行时不确定类型
as!
强制向下转型
危险
100% 确定类型
let dog = Dog()
let animal: Animal = dog as Animal // 向上转型,安全
let backToDog = animal as? Dog // 可选向下转型 → Dog?
let forceDog = animal as! Dog // 强制 → 崩溃风险
四、与 Any 和 AnyObject 配合
Any:可以是任意类型(包括结构体、枚举、函数)
let mixed: [Any] = [1, "hello", Dog(), 3.14, { print("closure") }]
for item in mixed {
switch item {
case let num as Int:
print("整数: \(num)")
case let str as String:
print("字符串: \(str)")
case let dog as Dog:
dog.bark()
case let closure as () -> Void:
closure()
default:
print("其他: \(item)")
}
}
AnyObject:仅限类实例(引用类型)
let objects: [AnyObject] = [Dog(), Cat(), NSString()]
for obj in objects {
if let dog = obj as? Dog {
dog.bark()
}
}
五、as 向上转型(Upcasting)
func playWith(animal: Animal) {
animal.makeSound()
}
let dog = Dog()
playWith(animal: dog as Animal) // 自动推导可省略 as
六、模式匹配中的类型转换
for pet in pets {
switch pet {
case let dog as Dog:
dog.bark()
case is Cat:
print("猫不叫")
default:
break
}
}
七、协议类型转换
protocol Flyable {
func fly()
}
class Bird: Animal, Flyable {
func fly() { print("飞翔") }
}
let bird = Bird()
if let flyer = bird as? Flyable {
flyer.fly()
}
// 检查是否遵守协议
if bird is Flyable {
print("会飞")
}
八、运行时类型信息(type(of:))
print(type(of: dog)) // Dog
print(type(of: animal)) // Animal(动态类型仍是 Dog)
九、常见错误写法
错误
正确
animal as Dog(父不能转子)
animal as? Dog
as! 用于不确定类型
用 as? + if let
Any 中用 as? Int 检查值类型
正确
十、完整实战:JSON 解析 + 类型转换
let json: Any = [
"name": "Tom",
"age": 25,
"pets": [
["type": "dog", "name": "旺财"],
["type": "cat", "name": "咪咪"]
]
]
if let dict = json as? [String: Any],
let name = dict["name"] as? String,
let pets = dict["pets"] as? [[String: String]] {
print("主人: \(name)")
for pet in pets {
if let type = pet["type"], let petName = pet["name"] {
switch type {
case "dog":
print("狗: \(petName)")
case "cat":
print("猫: \(petName)")
default:
break
}
}
}
}
最佳实践总结
场景
推荐写法
父类 → 子类(不确定)
as? + if let
子类 → 父类
as(可省略)
强制转换(确定)
as!(慎用)
多类型容器
Any + switch + as
协议检查
is / as?
避免崩溃
永远不要滥用 as!
常见面试题
is 和 as? 的区别? → is:检查类型,返回 Bool → as?:尝试转换,返回 Optional
以下代码会崩溃吗?
let animal: Animal = Dog()
let cat = animal as! Cat