以下是我想要做的事情(警告:前面的Scala非常糟糕):
def assignToFour[X](x : X, y : Something[X]) = x.y = 4
class M {
var m = 0;
}
val em = new M
assignToFour(em, M.m)
em.m == 4
显然,这根本不起作用,但是我正在寻找一种模式,它允许我在抽象中引用一个实例的成员,然后在稍后的某个时候访问实际实例上的该成员
如果这是Java,我会使用反射,但反思很糟糕,我希望Scala比Java更糟糕,它会有更好的选择。
答案 0 :(得分:4)
所以:
var m
,getter将命名为m
,setter方法将命名为m_=
从这里开始:
class M {
var m = 0
}
val x = new M
x.m目前为0,让我们改变一下......
这是一个以Function作为参数的方法,并使用值4
调用该函数:
def callWithFour(fn: Int=>Unit) = fn(4)
使用它:
callWithFour(x.m_=)
其中x.m_=
是实例m
上x
属性的setter方法
x.m
现在等于四。
答案 1 :(得分:3)
虽然结构类型是替代方案,但它们在内部使用反射。
你真正想做的是调用某个属性的setter,这样你就可以将它推广到函数调用:
def applyWith4[X,Y](x: X)(f: X => Int => Y) = f(x)(4)
此方法有两个参数:X
的一些实例和一个函数f
,可将X
转换为从Int
到某种类型Y
的函数(在你的情况下,这将是Unit
。
现在您可以使用
调用它applyWith4(em)(x => x.m = _)
或使用生成的setter m_=
的较短但不太可读的变体:
applyWith4(em)(_ m_=)
答案 2 :(得分:1)
您可以使用structural types
,因此您不会依赖于特定类型(虽然会失去一些灵活性而无法传递要更新的属性名称):
def assignToFour(x:{var y:Int}) = x.y = 4