无法在Swift中实现此设计模式?

时间:2015-12-10 22:48:05

标签: swift

我知道这个模式有一个名字,不记得它是什么。基本上有一个方法返回一个瞬态/蹦床的东西,通过API操纵原始。 Mediator可能吗?

我试图在Swift playground中的一个简单示例中实现它:

struct Count {
    var value = 0

    func adjuster() -> Adjuster {
        return Adjuster(target:self)
    }
}

struct Adjuster {
    var target:Count

    func increment(delta:Int) {
        self.target.value = self.target.value + delta
    }
}

var f = Count()

f.adjuster().increment(13)

首先,这有助于告诉我increment方法需要标记为mutating。我有点不清楚为什么。如果它改变它自己的var,我会明白为什么,而不是另一个的var。那好吧。所以我让IDE为我插入变异。但后来它与最后一行“测试”案件有关。它产生了这个错误:

...: error: cannot use mutating member on immutable value: function call returns immutable value
f.adjuster().increment(13)
~~^~~~~~~~~~

我并不完全了解这里的问题。它也不能为我“修复它”。那么这里发生了什么?如何实现这种模式?

2 个答案:

答案 0 :(得分:3)

如果您的方法改变了其属性(-ies),则使用shift up(与struct不同),必须使用class关键字进行标记。

在你的情况下它应该是:

mutating

来自documentation

  

结构和枚举是值类型。默认情况下,无法在其实例方法中修改值类型的属性。

     

但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择改变该方法的行为。然后,该方法可以从方法中改变(即更改)其属性,并且当方法结束时,它所做的任何更改都将写回原始结构。

“如果它改变它自己的var,我会明白为什么,而不是另一个变种。”

为什么它仍然抱怨“变异”的原因,虽然它不是它自己的属性,但另一个属性,是两者都是价值类型。这意味着如果您在mutating func increment(delta:Int) { ... } 内更改Count的属性,您仍然可以修改Adjuster(它是值类型,而不是对象)。因此需要Count

我没有看到mutating的实现,所以我不能确切地说出最后一条错误消息的原因,但我猜它有相同的根本原因,也就是说,值类型不是正确的适应设计模式。所以,你可能会更好地使用类,而不是结构。

答案 1 :(得分:2)

您必须将struct更改为class才能使其正常运行。

因为struct是按值复制的,所以在此行中

return Adjuster(target:self)

调整器将获得目标的新副本并保存。在increment方法中,您尝试修改self.target.value,这意味着您正在修改self.target,因此基本上修改了self

但还有更多问题,因为struct是值类型,所以

var count: Count // count.value = 0
var adjuster = count.adjuster()
adjuster.increment(1)

您希望count.value为1,但事实并非如此。 count.value将保持为0,adjuster.target.count将为1.您现在的代码现在非常混乱,您想知道错误是什么。

真正的问题是你正在用OOP实现设计模式和原始的纯函数模式,所以它们不能很好地协同工作。

如果您想要遵循一些最佳做法指南并且更喜欢struct而不是class,那么您也可以使用功能方法。即没有突变

struct Count {
    let value = 0
}

func increment(count:Count, delta:Int) -> Count {
    return Count(value:count.value + delta)
}