问题描述
考虑以下 Java 类:
public class C {
private int n;
private final int x;
private final int y;
public C(int n) {
this.n = n;
if (n < 0) {
x = -1;
y = -1;
} else {
x = 1;
y = 1;
}
}
}
x,y
依赖于 n
,设置后无法更改。这如何在 Scala 中实现? private val x
是最终的,但由于它是 val
,因此不能在“构造函数”中更改。 private var x
是私有的,但不是最终的,因此虽然它对用户不可见,但对于可能会错误修改它的程序员来说是可见的。
在单个“最终”变量的情况下,可以像 this answer 那样做,但是如果有两个(或更多,就像我实际编码的那样),那么我不确定怎么做。这是一种方法:
class C(n: Int) {
private val x = if (n < 0) -1 else 1
private val y = if (n < 0) -1 else 1 // code duplication
}
这是另一种方式:
class C(n: Int) {
private val (x,y) = if (n < 0) (-1,-1) else (1,1)
}
我可以使用后者,但感觉很迂回而且通常很难看,所以我想知道是否还有其他方法?上面的另一个缺点是我不能使用全大写的名称,我想这样做(即使这可能与 Scala 风格背道而驰)。
谢谢!
解决方法
// make the constructor private to avoid setting x,y directly
case class C private(n: Int,x: Int,y: Int)
// have a "smart constructor" in the companion object
// that implements your rule
object C {
def apply(n: Int): C = if (n < 0) C(n,-1,-1) else C(n,1,1)
}
// create an instance like this
C(1)
或者,根本不存储 x
和 y
,只在需要时计算它们
case class C(n: Int){
def x: Int = if (n < 0) -1 else 1
// could also make it a lazy-val if expensive
def y: Int = x // code re-use if the logic is really the same
}
,
我不确定您的解决方案有什么“丑陋”之处,对我来说似乎很好。 如果要使用大写,简单的方法是将它们一分为二:
val Abs = if (n < 0) -1 else 1
val Xyz = if (n < 0) -1 else 1
重新。 “代码重复”:如果您出于某种原因想要两个具有相同值的变量,您将不得不复制以一种或另一种方式设置它的代码。这不是语法问题,而是您的设计问题。 这:
x = -1;
y = -1;
其实也是在复制代码。
如果您非常想避免代码重复的可见性,那么您可以随时编写 val Xyz = Abc
,如果您认为这有帮助的话。