向上转型与向下转型基础
在超类和子类类型之间进行转换。
向上转型与向下转型基础 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
类型转换概述
类型转换让您可以在类层次结构中将一个实例视为另一种类型。它是在检查或改变静态类型,而不是转换数据。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let d = Dog(name: "Rex")
print(d.bark())类层次结构
类型转换需要存在层次结构。在这里,Dog 和 Cat 都继承自 Animal。Dog 就是 Animal。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let pet: Animal = Dog(name: "Rex")
print(pet.name)使用 as 向上转型
向上转型是将子类实例视为其超类。它总会成功,因此请使用普通的 as 运算符。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let dog = Dog(name: "Rex")
let asAnimal = dog as Animal
print(asAnimal.name)为什么要向上转型
向上转型适合将不同的子类存放在一起,例如放入一个类型为公共超类的数组中。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let zoo: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for a in zoo { print(a.name) }向上转型始终安全
由于每个子类实例也都是有效的超类实例,编译器接受使用 as 进行向上转型,不存在失败风险。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let cat = Cat(name: "Mia")
let animal = cat as Animal
print("Treated as Animal:", animal.name)向上转型后失去访问权限
一旦以超类类型存储,您只能调用超类成员。只有向下转型后,才能访问 Dog 特有的 bark()。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
print(a.name)
// a.bark() would not compile here向下转型简介
向下转型则相反:它将超类引用视为特定子类,以重新获得该子类的成员。此操作可能失败,因此需要使用 as? 或 as!。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
if let dog = a as? Dog {
print(dog.bark())
}为什么向下转型可能失败
编译器无法保证某个 Animal 确实是 Dog。它也可能是 Cat。正因为存在这种不确定性,向下转型必须经过检查。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Cat(name: "Mia")
let maybeDog = a as? Dog
print("Is it a Dog?", maybeDog != nil)在循环中进行向下转型
一种常见模式是:遍历超类数组,然后将每个元素向下转型,以便区别处理不同的子类。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let zoo: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for a in zoo {
if let dog = a as? Dog { print(dog.bark()) }
if let cat = a as? Cat { print(cat.meow()) }
}向上转型与向下转型总结
向上转型(as)朝基础类型方向进行,并且始终成功。向下转型(as? 或 as!)朝特定类型方向进行,并且可能失败。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let d = Dog(name: "Rex")
let up = d as Animal
let down = up as? Dog
print(up.name, down?.bark() ?? "no")只能在层次结构内进行类型转换
您只能在同一层次结构中的相关类型之间进行类型转换。无关类型不能相互转换。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
print(a is Animal)
print(a is Dog)快速检查
回想一下,哪种转型方向始终会成功。
回顾:向上转型与向下转型
您已经学到,类型转换适用于类层次结构内部;使用 as 向基础类型进行向上转型始终成功;而向特定子类进行向下转型可能失败,因此需要使用接下来介绍的检查型运算符。
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let pets: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for p in pets {
if let d = p as? Dog { print(d.bark()) } else { print(p.name) }
}常见问题解答
「向上转型与向下转型基础」课时是免费的吗?
是的 — 「向上转型与向下转型基础」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「向上转型与向下转型基础」这节课中我会学到什么?
在超类和子类类型之间进行转换。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「向上转型与向下转型基础」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 向上转型与向下转型基础
- 使用 as? 条件转型
- 使用 as! 强制转型及其风险
- 使用 is 检查类型