在我实例化对象之前可以引用对象的成员吗?

时间:2011-02-05 15:35:33

标签: scala

以下是我想要做的事情(警告:前面的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更糟糕,它会有更好的选择。

3 个答案:

答案 0 :(得分:4)

所以:

  • Scala的属性是作为一对方法实现的。对于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_=是实例mx属性的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