这就是我想要做的事情 -
class A(some args) {
var v: SomeType = null
def method1(args) = {
v = something1
...
method3
}
def method2(args) = {
v = something2
...
method3
}
def method3 = {
// uses v
}
}
在这种特定情况下,方法1和2是互斥的,并且在A的实例的生命周期中,其中一个被恰好调用一次。此外,v被分配一次。我宁愿把它变成val。但是因为我需要method2或method3的上下文来初始化v,所以我不能在构造函数中这样做。
如何实现这个" val"行为?我可以考虑修改method1和method2来应用方法,但我不喜欢这个想法。此外,method1和2具有相同的参数签名(因此应用需要更多信息来区分这两种类型的调用)。
答案 0 :(得分:8)
一个重要的问题是:你究竟打电话给什么" val行为"?给我" val行为"是在声明时立即分配的,可以静态强制执行。您似乎希望强制v
未分配两次。您可能还希望强制它在分配之前永远不会读取。您可以为此创建一个非常小的帮助框:
final class OnceBox[A] {
private[this] var value: Option[A] = None
def update(v: A): Unit = {
if (value.isDefined)
throw new IllegalStateException("Value assigned twice")
value = Some(v)
}
def apply(): A = {
value.getOrElse {
throw new IllegalStateException("Value not yet assigned")
}
}
}
现在你的片段:
class A(some args) {
val v = new OnceBox[SomeType]
def method1(args) = {
v() = something1
...
method3
}
def method2(args) = {
v() = something2
...
method3
}
def method3 = {
// uses v
v()
}
}
哦,开个玩笑,但是Ozma内置了单一赋值的val :-p
答案 1 :(得分:5)
与其他答案类似的想法,但不是子类型,而是一个字段。
scala> :pa
// Entering paste mode (ctrl-D to finish)
class A {
private[this] var context: Int = _
lazy val v: String =
context match {
case 1 => "one"
case 2 => "two"
case _ => ???
}
def m1() = { context = 1 ; v }
def m2() = { context = 2 ; v }
}
// Exiting paste mode, now interpreting.
defined class A
scala> val a = new A
a: A = A@62ce72ff
scala> a.m2
res0: String = two
scala> a.m1
res1: String = two
答案 2 :(得分:3)
这样的事情可能是:
render() {
const { potions, className } = this.state;
if (!potions) {
return (<p>Loading...</p>);
} else {
return (
<div className="{className}">
<ul>
{potions.map(potion => <li key={potion.id}>{potion.name}</li> )}
</ul>
</div>
);
}
}
或者,另一种可能性:
class A private (mtdType: Int, ...) {
val v = mdtType match {
case 1 => method1(...)
case 2 => method2(...)
}
}
object A {
def withMethod1(...) = new A(1, ...)
def withMethod2(...) = new A(2, ...)
}