deinit , 中文名叫做析构器。 与之对应的玩意叫 init(构造器)。
我们先上代码:
class Bank {
static var coinsInBank = 10_000
static func distribute(coins numberOfCoinsRequested: Int) -> Int {
let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
coinsInBank -= numberOfCoinsToVend
return numberOfCoinsToVend
}
static func recieve(coins: Int) {
coinsInBank += coins
}
}
class Player {
var coinsInpurse: Int
init(coins: Int) {
coinsInpurse = Bank.distribute(coins: coins)
}
func win(coins: Int) {
coinsInpurse += Bank.distribute(coins: coins)
}
deinit {
Bank.recieve(coins: coinsInpurse)
}
}
这里我们定义了一个银行类, coinsInBank这个存储属性 代表银行里存了多少钱。
distribute 方法用来往外出钱, 当它被实例化对象调用后, 实例化对象想要多少钱,我们在这个方法内和银行存款进行比较,如果银行余额大于要的钱,我们就返回要的钱,如果银行余额少于要的钱,我们就把银行总余额给return出去。
recieve 这个方法用来增加银行存款。
另一个Player类,代表玩家。 coinsInpurse 代表他一开始在实例化的时候向银行拿了多少钱。 也就是:
init(coins: Int) {
coinsInpurse = Bank.distribute(coins: coins)
}
我们来实例化对象看一看:
var player1: Player? = Player(coins: 500)
print("A new player has joined the game with \(player1!.coinsInpurse) coins")
print("There are now \(Bank.coinsInBank) coins left in the bank")
打印结果是:
A new player has joined the game with 500 coins
There are now 9500 coins left in the bank
可以看到现在实例化玩家时,银行类被实例化,银行初始余额一万块,大于玩家要的500 , 玩家以500 块的资金开始游戏。 银行余额剩余9500.
我们让他赢点钱:
player1!.win(coins: 800)
print("The bank now has \(Bank.coinsInBank) coins")
print(player1!.coinsInpurse)
player1 = nil
print(player1?.coinsInpurse)
print("PlayerOne has left the game")
print("The bank now has \(Bank.coinsInBank) coins")
打印结果是:
The bank now has 8700 coins
1300
nil
PlayerOne has left the game
The bank now has 10000 coins
我们可以看到,当 player1 = nil 的时候,变量player1 对Player 实例的引用失效,该实例就会被释放,内存回收。 在这之前,这个实例的析构器被自动调用, 执行
Bank.recieve(coins: coinsInpurse)
玩家的硬币被返还给银行。
OK 看完上面的代码我们再来总结一下deinit这个玩意:
- 在类的定义中,每个类最多只能有一个析构器,而且析构器不带任何参数
- 析构器在实例释放之前被自动调用,析构器是不允许被主动调用的。
- 子类继承了父类的析构器,并且在子类析构器实现的最后,父类的析构器会被自动调用。即使子类没有提供自己的析构器,父类的析构器也同样会被调用。
- 通常你不需要使用deinit,当你的实例化对象不在使用时,系统会自动帮你管理内存,但一些自定义的情况会涉及自己手动deinit, 例如下面这个我的另一篇文章: