我希望使用策略模式来注册实现协议的一组对象。当我设置这个时,尝试设置协议中的委托时,会出现编译错误。
为了讨论目的,我稍微改编了《Swift eBook》中的委托章节中的DiceGame。重要的更改如下:
- 协议DiceGame - 声明一个委托
- class SnakesAndLadders实现了DiceGame(因此协议和委托)
- class Games保存了3个SnakesAndLadders的实例 1) SnakesAndLadders 的具体类 2) 一个声明为协议DiceGame的'let'常量 3) 一个声明为协议DiceGame的'var'变量
如果我们使用具体类(snakesAndLadders),则可以很好地设置委托。然而,使用“let”将其保存为协议(diceGameAsLet)时,将出现编译错误,但如果我们将变量保存为“var”,则编译将通过。
很容易解决,但是委托本身永远不会改变,因此应将其保存为“let”常量,因为只有内部属性会发生变化。我可能没有理解协议及其工作原理和用法(也许是微妙但重要的)。
class Dice
{
func roll() -> Int
{
return 7 // always win :)
}
}
protocol DiceGame
{
// all DiceGames must work with a DiceGameDelegate
var delegate:DiceGameDelegate? {get set}
var dice: Dice {get}
func play()
}
protocol DiceGameDelegate
{
func gameDidStart( game:DiceGame )
func gameDidEnd( game:DiceGame )
}
class SnakesAndLadders:DiceGame
{
var delegate:DiceGameDelegate?
let dice = Dice()
func play()
{
delegate?.gameDidStart(self)
playGame()
delegate?.gameDidEnd(self)
}
private func playGame()
{
print("Playing the game here...")
}
}
class Games : DiceGameDelegate
{
let snakesAndLadders = SnakesAndLadders()
// hold the protocol, not the class
let diceGameAsLet:DiceGame = SnakesAndLadders()
var diceGameAsVar:DiceGame = SnakesAndLadders()
func setupDelegateAsClass()
{
// can assign the delegate if using the class
snakesAndLadders.delegate = self
}
func setupDelegateAsVar()
{
// if we use 'var' we can assign the delegate
diceGameAsVar.delegate = self
}
func setupDelegateAsLet()
{
// DOES NOT COMPILE - Why?
//
// We are not changing the dice game so want to use 'let', but it won't compile
// we are changing the delegate, which is declared as 'var' inside the protocol
diceGameAsLet.delegate = self
}
// MARK: - DiceGameDelegate
func gameDidStart( game:DiceGame )
{
print("Game Started")
}
func gameDidEnd( game:DiceGame )
{
print("Game Ended")
}
}
var delegate:DiceGameDelegate?
应该是一个弱引用吗?添加protocol DiceGame:class
解决了编译问题,现在这样做有意义了。 - Jim LeaskGame
的一个实例拥有一个SnakesAndLadders
的实例(例如snakesAndLadders
):这是从Game
实例到SnakesAndLadders
实例的强引用。在Game
的setupDelegateAsClass()
函数中,您将snakesAndLadders
的 delegate 属性的委托设置为Game
实例本身的实例:这是两个相同实例之间另一个方向上的强引用,从而创建了一个强引用循环。请参阅这个相关的问答。 - dfrib