我试图塑造一种可以逆转的关系。例如,北方的反面可能是南方。左派的反面可能是正确的。我想用一个案例类来表示我的关系。我找到了一个类似的解决方案,在这里使用了案例对象,但它并不是我想要的,here。
这是我的非功能性代码:
Promise.resolve(window.gapi.auth2.getAuthInstance().signIn()).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(googlePeopleSignedInCallback);
// Handle the initial sign-in state.
googlePeopleSignedInCallback(gapi.auth2.getAuthInstance().isSignedIn.get());
}, function (error) {
console.log(error);
});
可以更改此代码,以便:
答案 0 :(得分:4)
如果你真的想构建具有循环依赖关系的不可变对象的图形,你必须将opposite
声明为def
,并且(最好)将另外一个懒惰的val添加到混合中:
abstract class Relationship(val name: String) {
def opposite: Relationship
}
object Relationship {
/** Factory method */
def apply(nameA: String, nameB: String): Relationship = {
lazy val x: Relationship = new Relationship(nameA) {
lazy val opposite = new Relationship(nameB) {
def opposite = x
}
}
x
}
/** Extractor */
def unapply(r: Relationship): Option[(String, Relationship)] =
Some((r.name, r.opposite))
}
val ns = Relationship("North", "South")
println(ns.name)
println(ns.opposite.name)
println(ns.opposite.opposite.name)
println(ns.opposite.opposite.opposite.name)
如果你在这个循环依赖圈子上运行几百万轮,你可以很快说服自己没有任何不好的事情发生:
// just to demonstrate that it doesn't blow up in any way if you
// call it hundred million times:
// Should be "North"
println((1 to 100000000).foldLeft(ns)((r, _) => r.opposite).name)
确实打印了" North"。它不适用于案例类,但您可以随时添加自己的提取器,因此可以使用:
val Relationship(x, op) = ns
val Relationship(y, original) = op
println(s"Extracted x = $x y = $y")
它打印" North"和"南" x
和y
。
然而,更明显的做法是仅保存关系的两个组件,并添加opposite
作为构造相反对的方法。
case class Rel(a: String, b: String) {
def opposite: Rel = Rel(b, a)
}
实际上,这已在标准库中实现:
scala> val rel = ("North", "South")
rel: (String, String) = (North,South)
scala> rel.swap
res0: (String, String) = (South,North)
答案 1 :(得分:2)
你有循环依赖,这不会起作用。一种选择是:
case class Relationship(name: String)
并设置一个指定相反的setter。然后工厂会做:
def relationshipFactory(nameA:String, nameB:String): Relationship = {
val x:Relationship = Relationship(nameA)
val opposite = Relationship(nameB)
x.setOpposite(opposite)
opposite.setOpposite(x)
x
}
另一种选择:
case class Relationship(name: String) {
lazy val opposite = Utils.computeOpposite(this)
}
并且在Utils对象上具有相反的逻辑
还有另一种选择:可能你不想要几个South
个实例,因此你应该使用案例对象或枚举(更多内容见http://pedrorijo.com/blog/scala-enums/)
使用枚举,您可以使用模式匹配来执行该逻辑,而无需开销