Explicitly defined setter not found in assignment expression - scala

I have a small conundrum when it comes to Scala properties.
Various blogs and tutorials tell me that this:
class Something
{
var foo = 1
}
...can be specified as...
class Something
{
private var _field = 1
def foo = _field
def foo_(foo: Int) = _field = foo
}
This makes perfect sense to me, when doing assignment the compiler looks for a name_ method. Problem is it doesn't seem to work for me.
In the following real-world code (same thing happens in other classes as well):
class Camera
{
private var _position = Vector2.zero
def position: Vector2 = _position
def position_(position: Vector2) =
{
// Do boring transforms.
_position = position // position shadows outer scope so this does work.
}
}
// ...
val camera = new Camera
camera.position = Vector2(10, 0)
I get an error:
error: value position_= is not a member of Camera
camera.position = Vector(10, 0)
Instead I need to call it the following way to actually make it work: camera.position_(Vector2(10, 0)) which is neither beautiful nor readable.
In other scenarios, for example when trying to have public getters and private setters I faced the same problem.
What am I doing wrong?
Using scalac 2.8.0 on Java HotSpot VM 1.6

Your setters need to be named foo_= and position_=. If you name them foo_ and position_ the compiler doesn't recognize them as setters.

The signature to implement is:
def position_=(position: Vector2): Unit
So you want to correct your code like this:
def position_=(position: Vector2) { _position = position }

Related

What's a good way to handle unitialized private members in Scala objects?

It seems like having uninitialized members in the object body is forbidden in Scala objects..
I wanted to do something like (if it was in Java)
class MyClass {
private String str;
private String reassignString(String value) {
str = value;
}
I'm restricted on changing this code from object to class (since this repo is used by many teams) - what's a good Scala way to handle this kind of situation? Sorry the question is really vague.
Here is another bad idea:
object Lazy {
lazy val v = if (underlying ne null) underlying else ???
var underlying: String = null
}
Try(Lazy.v)
Lazy.underlying = "yes"
Try(Lazy.v)
Lazy.underlying = null
Try(Lazy.v)
The point is that the lazy val gets more than one shot at initialization, but is successfully initialized only once, if that's what you want.
Note that default initializer syntax is on its way out. They want you to write null if you want null.
My preferred default initializer:
var underlying: String = underlying
just to break the ice at dinner parties.
Uninitalized values are a bad idea, so str needs to be initialised to a valid value.
There are three obvious options:
Give str the default value
private var str: String = _
Pick you own default
private var str: String = "undefined"
Use Option
class MyClass {
private var str: Option[String] = None
private def reassignString(value: String): Unit = {
str = Some(value)
}
}
str in this Java code is initialized, to null. Scala simply requires you to make it explicit whether that's what you want.

Initialised class value evaluates to null in overridden method

I'm looking for some insight into scala internals. We've just come out the other side of a painful debug session, and found out our problem was caused by a unexpected null value that we had thought would be pre-initialised. We can't fathom why that would be the case.
Here is an extremely cut down example of the code which illustrates the problem (if it looks convoluted it's because it's much more complicated in real code, but i've left the basic structure alone in case it's significant).
trait A {
println("in A")
def usefulMethod
def overrideThisMethod = {
//defaultImplementation
}
val stubbableFunction = {
//do some stuff
val stubbableMethod = overrideThisMethod
//do some other stuff with stubbableMethod
}
}
class B extends A {
println("in B")
def usefulMethod = {
//do something with stubbableFunction
}
}
class StubB extends B {
println("in StubB")
var usefulVar = "super useful" //<<---this is the val that ends up being null
override def overrideThisMethod {
println("usefulVar = " + usefulVar)
}
}
If we kick off the chain of initialisation, this is what is printed to the console:
scala> val stub = new StubB
in A
usefulVar = null
in B
in StubB
My assumptions
I assume that in order to instantiate StubB, first we instantiate trait A, and then B and finally StubB: hence the printing order of ("in A ", "in B", "in StubB"). I assume stubbableFunction in trait A is evaluated on initialisation because it's a val, same for stubbableMethod.
From here on is where i get confused.
My question
When val overrideThisMethod is evaluated in trait A, i would expect the classloader to follow the chain downwards to StubB (which it does, you can tell because of the printing of "usefulVal = null") but... why is the value null here? How can overrideThisMethod in StubB be evaluated without first initialising the StubB class and therefore setting usefulVal? I didnt know you could have "orphaned" methods being evaluated this way - surely methods have to belong to a class which has to be initialised before you can call the method?
We actually solved the problem by changing the val stubbableFunction = to def stubbableFunction = in trait A, but we'd still really like to understand what was going on here. I'm looking forward to learning something interesting about how Scala (or maybe Java) works under the hood :)
edit: I changed the null value to be var and the same thing happens - question updated for clarity in response to m-z's answer
I stripped down the original code even more leaving the original behavior intact. I also renamed some methods and vals to express the semantics better (mostly function vs value):
trait A {
println("in A")
def overridableComputation = {
println("A::overridableComputation")
1
}
val stubbableValue = overridableComputation
def stubbableMethod = overridableComputation
}
class StubB extends A {
println("in StubB")
val usefulVal = "super useful" //<<---this is the val that ends up being null
override def overridableComputation = {
println("StubB::overridableComputation")
println("usefulVal = " + usefulVal)
2
}
}
When run it yields the following output:
in A
StubB::overridableComputation
usefulVal = null
in StubB
super useful
Here are some Scala implementation details to help us understand what is happening:
the main constructor is intertwined with the class definition, i.e. most of the code (except method definitions) between curly braces is put into the constructor;
each val of the class is implemented as a private field and a getter method, both field and method are named after val (JavaBean convention is not adhered to);
the value for the val is computed within the constructor and is used to initialize the field.
As m-z already noted, the initialization runs top down, i.e. the parent's class or trait constructor is called first, the child's constructor is called last. So here's what happens when you call new StubB():
A StubB object is allocated in heap, all its fields are set to default values depending on their types (0, 0.0, null, etc);
A::A is invoked first as the top-most constructor;
"in A" is printed;
in order to compute the value for stubbableValue overridableComputation is called, the catch is in fact that the overridden method is called, i.e. StubB::overridableComputation see What's wrong with overridable method calls in constructors? for more details;
"StubB::overridableComputation" is printed;
since usefulVal is not yet initialized by StubB::StubB it's default value is used, so "usefulVal = null" is printed;
2 is returned;
stubbableValue is initialized with the computed value of 2;
StubB::StubB is invoked as the next constructor in chain;
"in StubB" is printed;
the value for usefulVar is computed, in this case just the literal "super useful" is used;
usefulVar is initialized with the value of "super useful".
Since the value for stubbableValue is computed during constructor run
To prove these assumptions fernflower Java decompiler can be used. Here's how the above Scala code looks when decompiled to Java (I removed irrelevant #ScalaSignature annotations):
import scala.collection.mutable.StringBuilder;
public class A {
private final int stubbableValue;
public int overridableComputation() {
.MODULE$.println("A::overridableComputation");
return 1;
}
public int stubbableValue() {
return this.stubbableValue;
}
public int stubbableMethod() {
return this.overridableComputation();
}
public A() {
.MODULE$.println("in A");
// Note, that overridden method is called below!
this.stubbableValue = this.overridableComputation();
}
}
public class StubB extends A {
private final String usefulVal;
public String usefulVal() {
return this.usefulVal;
}
public int overridableComputation() {
.MODULE$.println("StubB::overridableComputation");
.MODULE$.println(
(new StringBuilder()).append("usefulVal = ")
.append(this.usefulVal())
.toString()
);
return 2;
}
public StubB() {
.MODULE$.println("in StubB");
this.usefulVal = "super useful";
}
}
In case A is a trait instead of a class the code is a bit more verbose, but behavior is consistent with the class A variant. Since JVM doesn't support multiple inheritance Scala compiler splits a trait into a abstract helper class which only contains static members and an interface:
import scala.collection.mutable.StringBuilder;
public abstract class A$class {
public static int overridableComputation(A $this) {
.MODULE$.println("A::overridableComputation");
return 1;
}
public static int stubbableMethod(A $this) {
return $this.overridableComputation();
}
public static void $init$(A $this) {
.MODULE$.println("in A");
$this.so32501595$A$_setter_$stubbableValue_$eq($this.overridableComputation());
}
}
public interface A {
void so32501595$A$_setter_$stubbableValue_$eq(int var1);
int overridableComputation();
int stubbableValue();
int stubbableMethod();
}
public class StubB implements A {
private final String usefulVal;
private final int stubbableValue;
public int stubbableValue() {
return this.stubbableValue;
}
public void so32501595$A$_setter_$stubbableValue_$eq(int x$1) {
this.stubbableValue = x$1;
}
public String usefulVal() {
return this.usefulVal;
}
public int overridableComputation() {
.MODULE$.println("StubB::overridableComputation");
.MODULE$.println(
(new StringBuilder()).append("usefulVal = ")
.append(this.usefulVal())
.toString()
);
return 2;
}
public StubB() {
A$class.$init$(this);
.MODULE$.println("in StubB");
this.usefulVal = "super useful";
}
}
Remember that a val is rendered into a field and a method? Since several traits can be mixed into a single class, a trait cannot be implemented as a class. Therefore, the method part of a val is put into an interface, while a field part is put into the class that a trait gets mixed into.
The abstract class contains the code of all the trait's methods, access to the member fields is provided by passing $this explicitly.

'Ambiguous reference to overloaded definition' when override method in derived class

I've got the following code:
import com.github.nscala_time.time.Imports._
class Account {
def balance(date: DateTime): Double = {
/* some logic that calculates balance on given date */
val calculatedBalance = 42
calculatedBalance
}
def balance: Double = balance(DateTime.now)
}
class Deposit(val interestRate: Double) extends Account {
override def balance(date: DateTime): Double = {
/* some logic that calculates balance for deposit account */
val calculatedBalance = 100 * interestRate;
calculatedBalance
}
}
I try to use these classes in the following way:
val simpleAccount = new Account
val depositAccount = new Deposit(0.1)
val simpleBalanceOnDate = simpleAccount.balance(DateTime.now + 1.month) // A
val depositBalanceOnDate = depositAccount.balance(DateTime.now + 1.month) // B
val simpleBalance = simpleAccount.balance // C
val depositBalance = depositAccount.balance // D
Cases A, B and C are compiled without any errors, but for the line D I see error message:
Error:(28, 38) ambiguous reference to overloaded definition,
both method balance in class Deposit of type (date: com.github.nscala_time.time.Imports.DateTime)Double
and method balance in class Account of type => Double
match expected type ?
val depositBalance = depositAccount.balance
^
Can you please explain why there is a compilation error in case D and why there are no in case C?
Thanks in advance!
I suppose the compiler is confused about parameterless method inheritance, although I can't explain why honestly, for a quick solution this should work:
class Account {
{ ... }
def balance(): Double = balance(DateTime.now)
}
val depositAccount = new Deposit(0.1)
val depositBalance = depositAccount.balance()
Why this happens is obscure to me, maybe somebody else knows how the scala compiler is seeing parameterless method inheritance.
Also reading around, specifically Programming in Scala:
Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state).
This convention supports the uniform access principle,1 which says that client code should not be affected by a decision to implement an attribute as a field or method. For instance, we could have chosen to implement width and height as fields instead of methods, simply by changing the def in each definition to a val:
abstract class Element {
def contents: Array[String]
val height = contents.length
val width =
if (height == 0) 0 else contents(0).length
}
The two pairs of definitions are completely equivalent from a client's point of view. The only difference is that field accesses might be slightly faster than method invocations, because the field values are pre-computed when the class is initialized, instead of being computed on each method call. On the other hand, the fields require extra memory space in each Element object. So it depends on the usage profile of a class whether an attribute is better represented as a field or method, and that usage profile might change over time. The point is that clients of the Element class should not be affected when its internal implementation changes.
Why don't you provide a default argument like this:
class Account {
def balance(date: DateTime = DateTime.now): Double = {
/* some logic that calculates balance on given date */
val calculatedBalance = 42
calculatedBalance
}
}
class Deposit(val interestRate: Double) extends Account {
override def balance(date: DateTime): Double = {
/* some logic that calculates balance for deposit account */
val calculatedBalance = 100 * interestRate;
calculatedBalance
}
}
val simpleBalanceOnDate = simpleAccount.balance(1) // A
val depositBalanceOnDate = depositAccount.balance(1) // B
val simpleBalance = simpleAccount.balance() // C
val depositBalance = depositAccount.balance() // D

How to create a Scala class with private field with public getter, and primary constructor taking a parameter of the same name

Search results so far have led me to believe this is impossible without either a non-primary constructor
class Foo { // NOT OK: 2 extra lines--doesn't leverage Scala's conciseness
private var _x = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
or sacrificing the name of the parameter in the primary constructor (making calls using named parameters ugly)
class Foo(private var _x: Int) { // OK: concise
def x = _x
}
val f = new Foo(_x = 123) // NOT OK: named parameter should be 'x' not '_x'
ideally, one could do something like this:
class Foo(private var x: Int) { // OK: concise
// make just the getter public
public x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
I know named parameters are a new thing in the Java world, so it's probably not that important to most, but coming from a language where named parameters are more popular (Python), this issue immediately pops up.
So my question is: is this possible? (probably not), and if not, why is such an (in my opinion) important use case left uncovered by the language design? By that, I mean that the code either has to sacrifice clean naming or concise definitions, which is a hallmark of Scala.
P.S. Consider the case where a public field needs suddenly to be made private, while keeping the getter public, in which case the developer has to change 1 line and add 3 lines to achieve the effect while keeping the interface identical:
class Foo(var x: Int) {} // no boilerplate
->
class Foo { // lots of boilerplate
private var _x: Int = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
Whether this is indeed a design flaw is rather debatable. One would consider that complicating the syntax to allow this particular use case is not worthwhile.
Also, Scala is after all a predominantly functional language, so the presence of vars in your program should not be that frequent, again raising the question if this particular use case needs to be handled in a special way.
However, it seems that a simple solution to your problem would be to use an apply method in the companion object:
class Foo private(private var _x: Int) {
def x = _x
}
object Foo {
def apply(x: Int): Foo = new Foo(x)
}
Usage:
val f = Foo(x = 3)
println(f.x)
LATER EDIT:
Here is a solution similar to what you originally requested, but that changes the naming a bit:
class Foo(initialX: Int) {
private var _x = initialX
def x = _x
}
Usage:
val f = new Foo(initialX = 3)
The concept you are trying to express, which is an object whose state is mutable from within the object and yet immutable from the perspective of other objects ... that would probably be expressed as an Akka actor within the context of an actor system. Outside the context of an actor system, it would seem to be a Java conception of what it means to be an object, transplanted to Scala.
import akka.actor.Actor
class Foo(var x: Int) extends Actor {
import Foo._
def receive = {
case WhatIsX => sender ! x
}
}
object Foo {
object WhatIsX
}
Not sure about earlier versions, but In Scala 3 it can easily be implemented like follows:
// class with no argument constructor
class Foo {
// prive field
private var _x: Int = 0
// public getter
def x: Int = _x
// public setter
def x_=(newValue: Int): Unit =
_x = newValue
//auxiliary constructor
def this(value: Int) =
this()
_x = value
}
Note
Any definition within the primary constructor makes the definition public, unless you prepend it with private modifier
Append _= after a method name with Unit return type to make it a setter
Prepending a constructor parameter neither with val nor with var, makes it private
Then it follows:
val noArgFoo = Foo() // no argument case
println(noArgFoo.x) // the public getter prints 0
val withArgFoo = Foo(5) // with argument case
println(withArgFoo.x) // the public getter prints 5
noArgFoo.x = 100 // use the public setter to update x value
println(noArgFoo.x) // the public getter prints 100
withArgFoo.x = 1000 // use the public setter to update x value
println(withArgFoo.x) // the public getter prints 1000
This solution is exactly what you asked; in a principled way and without any ad hoc workaround e.g. using companion objects and the apply method.

Scala subclass field hiding superclass var only within member function

I had a very hard time to find this bug where it seems field pos of class Icon hides class Element's pos field, only within the draw function.
case class Vector2(val x: Float, val y: Float) { ... }
abstract class Element(var pos: Vector2) {
def draw(): Unit
}
class Icon(pos: Vector2, var texture: String) extends Element(pos) {
override def draw() {
...
GL11.glTranslatef(pos.x, pos.y, 0f)
...
}
}
Later on:
// Create an icon with an initial position
val icon = new Icon(pos = Vector2(40,20), "crosshair")
// Draw all elements
elements.foreach{_.draw()} // => draws icon at (40,20)
// Setting a new position for icon
icon.pos = Vector2(100,200)
// See if it worked
Log.info(icon.pos.toString()) // => this prints Vector2(100,200)
// Draw all elements
elements.foreach{_.draw()} // => still draws icon at (40,20)
I've seen this post and I've tried:
Making the var abstract in the base class: this prevents me from setting a new pos to an Element
Renaming the constructor parameter (e.g. _pos): I won't do this because this will screw the API
Overriding the var in the derived class: only to be told by the compiler that I can't override a mutable variable
What's the way out ?
Just explicitly dereference this:
class Icon(pos: Vector2, var texture: String) extends Element(pos) {
override def draw() {
...
GL11.glTranslatef(this.pos.x, this.pos.y, 0f)
...
}
}
Given that the shadowing only happens inside Icon, everywhere else (included in derived classes) you can keep using just pos (no need for this.pos).
UPDATE: No wait, this does not work! I'd call that a compiler bug. It seems that this.pos is treated as just pos even though they should not (IMHO) be the same thing.
There is a simple workaround though:
class Icon(pos: Vector2) extends Element(pos) {
private def self = this
override def draw() {
println(self.pos.x, self.pos.y, 0f)
}
}
UPDATE 2: This is a reply to a comment, which would not fit in another comment.
Randall Schulz says:
I don't believe it's a bug.
Well it certainly looks like it is a bug, or at the very least an inconsistentcy for which I'd like to have a rationale.
The first thing to note is that in my work around above, self eq this. They really point to the very same reference, and in addition have the same static type. Then how come that self.pos and this.pos return two different things (regardless of what the "right" thing to return is)? In other word, self is an alias to this, and aliases should necessarily all behave the same.
Now, the reason why I think that this.pos should denote the variable in Element and not the parameter to Icon's constructor is simple. This parameter is not preceded with val and is thus really a mere parameter (not a val). As such it is accessible in class Icon only because of lexical scoping. It is not a member of Icon, not even a private one (the fact that under the hood a private field is generated does not change the semantics of the language). And if the pos parameter is not a member there is no reason that this.pos should return it.
Obviously, this argument boils down to whether or not the parameter is also a member of the class. To me it clearly is not, but if in fact it supposed to automatically also be a member (I'm still looking in the spec for any mention of this) then it is indeed logical that self.pos returns the value of the parameter instead of the current value of the var in the base class (this still would not explain how self.pos and this.pos can mean a different thing though).
That's one of the reason self-types (the (usually) unconstrained variety that use a name other than this) exist.
Well, no. self-types are irrelevant. An unconstrained self-type just introduce an alias, so the alias points to the same reference as this (and if unconstrained, has the same static type). So using the alias should very much not change what is returned.
And actually, it does not:
class Icon(pos: Vector2) extends Element(pos) { self =>
override def draw() {
println(self.pos.x, self.pos.y, 0f)
}
}
val icon = new Icon(Vector2(1, 2))
icon.draw() // prints "(1.0,2.0,0.0)" as expected
icon.pos = Vector2(3, 4)
icon.draw() // oops, still prints "(1.0,2.0,0.0)"!
As you can see the self type did not help: self.pos still points to the parameter instead of the variable.
To fix this you might be tempted to try to explictly type self as Element:
class Icon(pos: Vector2) extends Element(pos) { self: Element =>
But it does not change anything.
Constructor parameters are visible in a class body, that's just how things work. It is weird to have a private val shadow a public var, I grant you, but that's that. In the particular snippet you showed, you can do this:
abstract class Element {
def pos: Vector2
def pos_=(x: Vector2): Unit
def draw(): Unit
}
and then
class Icon(var pos: Vector2, var texture: String) extends Element {
override def draw() {
...
GL11.glTranslatef(pos.x, pos.y, 0f)
...
}
}
But it won't help if you just want to initialize Element with a value, instead of declaring a var on whatever is extending Element. My own advice is to avoid var on constructors, use something like initialPos, and initialize the var in the body.