Swift中的相互非可选引用循环

Swift中的相互非可选引用循环,第1张

概述考虑以下用例: 在某个游戏的模型中,你有一个Player类.每个玩家都有一个无主的让对手:玩家代表他们正在对抗的对手.这些总是成对创建,并且玩家必须始终拥有对手,因为它是非可选的.然而,这很难建模,因为一个玩家必须先创建另一个玩家,并且第一个玩家在创建第二个玩家之前不会有对手! 通过一些丑陋的黑客攻击,我想出了这个解决方案: class Player { private static le 考虑以下用例:

在某个游戏的模型中,你有一个Player类.每个玩家都有一个无主的让对手:玩家代表他们正在对抗的对手.这些总是成对创建,并且玩家必须始终拥有对手,因为它是非可选的.然而,这很难建模,因为一个玩家必须先创建另一个玩家,并且第一个玩家在创建第二个玩家之前不会有对手!

通过一些丑陋的黑客攻击,我想出了这个解决方案:

class Player {    private static let placeholder: Player = Player(opponent: .placeholder,name: "")    private init(opponent: Player,name: String) {        self.opponent = opponent        self.name = name    }    uNowned var opponent: Player    let name: String    class func getPair(named names: (String,String)) -> (Player,Player) {        let p1 = Player(opponent: .placeholder,name: names.0)        let p2 = Player(opponent: p1,name: names.1)        p1.opponent = p2        return (p1,p2)    }}let pair = Player.getPair(named:("P1","P2"))print(pair.0.opponent.name)print(pair.1.opponent.name)

哪个效果很好.但是,我无法将对手变成常数.一种解决方案是让对手成为没有集合的计算属性,由私有var支持,但我想避免这种情况.

我试图用Swift指针进行一些黑客攻击,并提出:

class func getPair(named names: (String,Player) {    var p1 = Player(opponent: .placeholder,name: names.0 + "FAKE")    let p2 = Player(opponent: p1,name: names.1)    withUnsafeMutablePointer(to: &p1) {        var trueP1 = Player(opponent: p2,name: names.0)        
(lldb) p p1(Player2.Player) $R3 = 0x0000000101004390 {  opponent = 0x0000000100702940 {    opponent = <uninitialized>    name = ""  }  name = "P1FAKE"}
.moveAssign(from: &trueP1,count: 1) } return (p1,p2)}

但这给了一个段错误.此外,在使用lldb进行调试时,我们可以看到在初始化p1之后,我们有:

(lldb) p p1(Player2.Player) $R5 = 0x00000001010062d0 {  opponent = 0x00000001010062a0 {    opponent = 0x0000000101004390 {      opponent = 0x0000000100702940 {        opponent = <uninitialized>        name = ""      }      name = "P1FAKE"    }    name = "P2"  }  name = "P1"}(lldb) p p2(Player2.Player) $R4 = 0x00000001010062a0 {  opponent = 0x0000000101004390 {    opponent = 0x0000000100702940 {      opponent = <uninitialized>      name = ""    }    name = "P1FAKE"  }  name = "P2"}

但是在函数结束时,lldb显示了这个:

因此p1正确指向p2,但p2仍指向旧p1.更重要的是,p1实际上改变了地址!

我的问题是双重的:

>是否有更清晰,更“快捷”的方式来创建这种相互非可选引用的结构?
>如果没有,我对Swift中的UnsafeMutablePointers之类的误解是什么使得上面的代码不起作用?

解决方法 在搞砸了一段时间之后,看起来你想要做的事情可能是不可能的,并且与Swift并没有真正相同.更重要的是,它可能是一个有缺陷的方法开始.

就Swift而言,初始化器需要在返回之前初始化所有存储的值.出于多种原因,我不打算这样做.当初始化时无法保证/计算值时,将使用选项,IUO和计算值.如果您不想要Optionals,IUO或计算值,但仍希望在初始化后取消设置一些存储的值,那么您就想要吃蛋糕并吃掉它.

就设计而言,如果您需要将两个对象链接得如此紧密以至于在初始化时需要彼此,则您的模型(IMO)会被破坏.这是分层数据结构解决得很好的确切问题.在你的具体例子中,似乎很清楚你需要某种Match或Competition对象来创建和管理两个玩家之间的关系,我知道你的问题更接近于“这是否可能”而不是“应该完成”,但我想不出任何不是坏主意的情况.从根本上说它打破了封装.

Player对象应该管理和跟踪Player对象中存在的东西,而Player类中唯一的托管关系应该是它的子对象.任何兄弟关系都应该由它的父母访问/设置.

这成为一个更清晰的规模问题.如果你想添加第三个玩家怎么办? 50岁左右?然后,您必须初始化并将每个玩家连接到其他玩家,然后才能使用任何玩家.如果您想要添加或删除播放器,您必须同时为每个连接的播放器执行此 *** 作,并阻止发生任何事情.

另一个问题是它在任何其他情况下都无法使用.如果设计得当,玩家可以在所有类型的游戏中使用.而目前的设计允许它仅在1v1情况下使用.对于任何其他情况,您将不得不重新编写它,您的代码库将会分歧.

总而言之,你想要的东西在Swift中可能是不可能的,但是如果它成为可能的话,反正几乎肯定是一个坏主意:)

对不起文章,希望你觉得它有用!

总结

以上是内存溢出为你收集整理的Swift中的相互非可选引用循环全部内容,希望文章能够帮你解决Swift中的相互非可选引用循环所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1004469.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存