我有点难过这个问题是多么愚蠢而且有严重的思维空白,但我想我还是会问.
我有一个对象Foo,有几个字段.我想要一个可以更改其任何字段的方法,具体取决于作为参数传入的字段.像这样:
class Foo {
var x = 0
var y = 0
}
class Bar {
def changeFooField(field : Int) = {
field = 1
}
}
Run Code Online (Sandbox Code Playgroud)
我不能这样使用吗?:
changeFooField(foo.x)
Run Code Online (Sandbox Code Playgroud)
如果没有,我该如何做到这一点?
Deb*_*ski 16
一个常见的习惯用法是传递一个显式的setter方法,该方法负责改变值.
class Foo {
var x = 0
var y = 0
}
class Bar {
def changeFooField(setter: (Int) => Unit) = {
setter(1)
}
}
val foo = new Foo
val bar = new Bar
bar.changeFooField(foo.x = _) // or equivalent: bar.changeFooField((i: Int) => foo.x = i)
assert(foo.x == 1)
Run Code Online (Sandbox Code Playgroud)
(foo.x = _)
是一个简单的临时闭包,允许写访问foo.x
.没有必要将此setter API添加到Foo
自身.
因此,事实证明,setter方法(foo.x=
或者更确切地说foo.x_=
)作为参数传递,与传递任何其他方法完全相同.你必须记住这一点,val
并且var
在Scala中实际上并没有指定变量,而是创建了用于访问实际(隐藏)变量的方法.(val
只创建一个getter方法,var
当然创建getter和setter).
par*_*tic 13
你不能.您需要将字段值包含在对象中:
class Field[T]( var value: T )
class Foo {
val x = new Field(0)
val y = new Field(0)
}
class Bar {
def changeFooField( field: Field[Int] ) {
field.value = 1
}
}
val f = new Foo
(new Bar).changeFooField( f.x )
println( f.x.value + " / " + f.y.value ) // prints "1 / 0"
Run Code Online (Sandbox Code Playgroud)
与上面的所有答案相反,这实际上在Scala中非常可行而没有编写任何特殊的包装类.
首先,您需要知道对于任何非私有类var,例如原始问题中使用的那些,Scala会自动生成getter和setter.因此,如果我们有一个名为"color"的var,Scala会自动创建一个名为"color"的getter和一个名为"color_ ="的setter.
接下来,您需要知道Scala允许您通过在其上调用特殊的"_"方法来获取对任何方法的引用(在消除歧义之前需要一个空格).
最后将这些事实放在一起,您可以轻松获得任何var的getter/setter的类型安全引用,并使用该引用动态设置/获取该var的值:
class Foo {
var x = 0
}
object Foo {
def setField[T](setter: T => Unit, value: T) {setter(value)}
def getField[T](getter: () => T ) = {getter()}
}
val f = new Foo
val xsetter = f.x_= _
val xgetter = f.x _
Foo.setField(xsetter, 3)
println(f.x) //prints 3
println(Foo.getField(xgetter)) //prints 3
Run Code Online (Sandbox Code Playgroud)