gpt4 book ai didi

swift - 设置委托(delegate)会产生编译错误

转载 作者:搜寻专家 更新时间:2023-10-31 08:16:32 25 4
gpt4 key购买 nike

我想使用策略模式来注册一组实现协议(protocol)的对象。当我设置它时,我在尝试设置作为协议(protocol)一部分的委托(delegate)时遇到编译错误。

出于讨论的目的,我对 Swift 电子书的委托(delegate)章节中的 DiceGame 进行了轻微修改。意义的变化是:

  • 协议(protocol) DiceGame - 声明一个委托(delegate)
  • 类 SnakesAndLadders 实现了 DiceGame(因此实现了协议(protocol)和委托(delegate))
  • Games 类包含 3 个 SnakesAndLadders 实例1) SnakesAndLadders 的具体类2) 协议(protocol) DiceGame 的“let”常量3) DiceGame 协议(protocol)的“var”变量

如果我们使用具体类 (snakesAndLadders),我们可以很好地设置委托(delegate)。但是,如果我们使用“let”将其保存为协议(protocol) (diceGameAsLet),则会出现编译错误,但如果我们将变量保存为“var”(diceGameAsVar),则会编译。

变通很容易,但是,委托(delegate)本身永远不会改变,因此应该作为“let”常量保存,因为只有内部属性会改变。我一定不了解有关协议(protocol)及其工作方式和应如何使用的某些内容(可能很微妙但很重要)。

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")
}
}

最佳答案

DiceGame 是您用作类型的异构协议(protocol); Swift 会将此类型视为值类型,因此(就像对于结构一样),更改其可变属性也会改变协议(protocol)类型本身的实例。

但是,如果您将 : class 关键字添加到 DiceGame 协议(protocol)中,Swift 会将其视为引用类型,从而允许您改变它的实例成员,而不改变实例本身。请注意,这会将协议(protocol)限制为仅按类类型符合

protocol DiceGame: class { ... }

添加上述内容后,将允许不可变的 diceGameAsLet:s 属性发生变化。


在这种情况下,值得一提的是 : class 关键字通常用于限制用作委托(delegate)的协议(protocol)(例如,您的示例中的 DiceGameDelegate)仅符合按类类型。有了这个额外的约束,委托(delegate)可以用作委托(delegate)所有者(例如某个类)只持有 weak 引用的类型,这在对委托(delegate)的强引用可能创建保留循环的上下文中很有用.

参见例如this answer的第二部分了解详情。

关于swift - 设置委托(delegate)会产生编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36019265/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com