Can refer to a member of an object before I've instantiated the object?
Here's what I want to do (warning: extremely broken Scala ahead):
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
Obviously, that won't work at all, but I'm looking for a pattern that will allow me to refer to an member of an instance in the abstract and then at some later point, access that member on an actual instance.
If this were Java, I would use reflection, but reflection s开发者_StackOverflow社区ucks and I am hoping Scala, which sucks so much less than Java, would have a better alternative.
So:
- Scala's properties are implemented as a pair of methods. For a
var m
the getter will be namedm
and the setter method will be namedm_=
- Methods can be automatically lifted to functions
- Functions can be passed around as first-class values
Starting here:
class M {
var m = 0
}
val x = new M
x.m is currently 0, let's change that...
Here's a method that takes a Function as its argument, and calls that function with the value 4
:
def callWithFour(fn: Int=>Unit) = fn(4)
And using it:
callWithFour(x.m_=)
Where x.m_=
is the setter method for the m
property on the instance x
x.m
is now equal to four.
While structural types are an alternative they use reflection internally.
What you actually want to do is invoke the setter of some property so you can generalize it to a function call:
def applyWith4[X,Y](x: X)(f: X => Int => Y) = f(x)(4)
This method takes two arguments: some instance of X
and one function f
that turns your X
into a function from Int
to some type Y
(this will be Unit
in your case).
Now you can invoke it using
applyWith4(em)(x => x.m = _)
or in a shorter but less readable variant using the generated setter m_=
:
applyWith4(em)(_ m_=)
You can use structural types
, so you won't depend on a specific type (though lose some flexibility no being able to pass the name of the property to update):
def assignToFour(x:{var y:Int}) = x.y = 4
精彩评论