Swift编程:多态、类型转换、类与结构体差异及属性详解
立即解锁
发布时间: 2025-09-12 01:52:37 阅读量: 4 订阅数: 26 AIGC 

### Swift编程:多态、类型转换、类与结构体差异及属性详解
#### 1. 多态与类型转换
多态意味着一个对象可以有多种形式。例如,每个僵尸(Zombie)也是一个怪物(Monster),因为僵尸继承自怪物,所以可以把僵尸实例当作怪物来处理,但反过来不一定安全。
```swift
let fredTheZombie: Monster = Zombie()
fredTheZombie.town = myTown
fredTheZombie.terrorizeTown()
fredTheZombie.town?.printDescription()
```
这里声明了一个`Monster`类型的变量`fredTheZombie`,但存储了一个`Zombie`类型的值。编译器根据声明的变量类型来决定后续可以对该变量进行的操作。只要只对变量执行怪物相关的操作,编译器就会认为这是可行的。
当尝试访问仅存在于`Zombie`中的属性时,会出现编译器错误:
```swift
let fredTheZombie: Monster = Zombie()
fredTheZombie.town = myTown
fredTheZombie.terrorizeTown()
fredTheZombie.town?.printDescription()
fredTheZombie.walksWithLimp = true
```
可以使用`as`关键字进行类型转换。从更通用的类型(超类)转换为更具体的类型(子类)称为向下转换,这是不安全的。有两种转换方式:
- **强制转换(`as!`)**:如果尝试访问实例没有的属性,程序会在转换处崩溃。
```swift
(fredTheZombie as! Zombie).walksWithLimp = true
```
- **条件转换(`as?`)**:如果转换在运行时失败,转换表达式将返回`nil`,这通常是更安全的选择。
```swift
(fredTheZombie as? Zombie)?.walksWithLimp = true
```
从子类转换为其超类称为向上转换,这总是安全的,使用`as`关键字即可。还可以使用`is`关键字在运行时检查实例的类型:
```swift
if fredTheZombie is Zombie {
print("I knew it!")
}
```
多态和类型转换也适用于函数。接受`Monster`类型参数的函数可以接受`Zombie`类型的参数,但反之则可能需要不安全的类型转换。
#### 2. 类与结构体的差异
类和结构体的一个显著区别是类支持继承,而结构体不支持。但更本质的区别在于内存管理。
结构体和枚举是值类型,当复制一个结构体变量时,会复制整个实例。例如:
```swift
var myTown = Town()
var yourTown = myTown
myTown.changePopulation(by: 500)
print("myTown has \(myTown.population) and yourTown has \(yourTown.population)")
```
`yourTown`是`myTown`的一个副本,修改`myTown`的人口不会影响`yourTown`。
类是引用类型,类变量只存储对实例实际存储位置的引用。例如:
```swift
var frederickTheZombie = fredTheZombie
frederickTheZombie.name = "Frederick"
print("Fred's name is \(fredTheZombie.name)")
```
这里`frederickTheZombie`和`fredTheZombie`引用同一个僵尸实例,修改`frederickTheZombie`的名字会影响`fredTheZombie`。
类的实例方法不需要使用`mutating`关键字,因为`self`已经是对实例的引用,而不是副本。
```mermaid
graph LR
A[类型] --> B[值类型(结构体、枚举)]
A --> C[引用类型(类)]
B --> D[复制整个实例]
C --> E[存储引用]
```
#### 3. 挑战任务
- **青铜挑战**:修复程序中的一个bug。当僵尸袭击人口少于10的城镇时,城镇人口会变为负数。修改`Town`类的`changePopulation(by:)`方法,确保城镇人口不会为负数。
- **白银挑战**:创建`Monster`的另一个子类`Vampire`,添加`thralls`属性来存储吸血鬼的奴隶。重写`terrorizeTown()`方法,在城镇有人的情况下,捕获一个镇民并将其变成吸血鬼奴隶,同时减少城镇人口。
#### 4. 类型方法
除了实例方法,还可以定义类型方法,用于处理类型级别的信息。
对于值类型,使用`static`关键字定义类型方法:
```swift
struct Square {
static func numberOfSides() -> Int {
return 4
}
}
```
对于类,使用`class`关键字定义类型方法:
```swift
class Zombie: Monster {
class func makeSpookyNoise() -> String {
return "Brains..."
}
}
```
子类可以重写类方法。如果不想让子类重写类方法,可以使用`static`或`final class`关键字。
类型方法可以调用其他类型方法,甚至可以处理类型属性,但不能调用实
0
0
复制全文
相关推荐










