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.
Related
New to scala and trying to get the hang of the class system. Here's a simple set up:
sealed trait Shape{
def sides:Int
}
final case class Square() extends Shape {
def sides() = 4
}
final case class Triangle() extends Shape {
def sides() = 3
}
Now, I want to create a function that takes anything of type shape, which we know will have a sides() method implemented, and make use of that method.
def someFunction(a: Shape)={
val aShape = a()
aShape.sides()
}
But this hits an error at val aShape = a(), as there's no type a.
I realize that in this example, it's excessive to create someFunction, since sides() can be accessed directly from the objects. But my primary question is in the context of someFunction - I'd like to pass a class to a function, and instantiate an object of that class and then do something with that object. Thanks for your help.
What are you trying to do with that line of code? You already have a shape, the one passed in called a. Just remove that line and call a.sides().
Stylistically, there are several problems. First of all, class names should start with a capital letter. Second, sides seems like an immutable property, not a mutating method, so it should be declared and overridden with no parentheses. You also need override modifiers in your subclass. Last, you can do without the empty braces: {4} should just be 4.
There is several methods to do this. One is a complex one using reflection, second is little bit simplier, using a builder and third is most straightforward for your use case.
Just change definition of someFunction to
def someFunction(a: ()=>Shape)={
val aShape = a()
aShape.sides
}
so someFunction(Square) return 4 and someFunction(Triangle) returns 3 . Note this work only with case classes because real thing, we are passing here is not class itself, but it's auto-generated companion object
But more often there no need to define classes, you could write inside any context except top level thing just like
def square() = new Shape{
def sides() = 4
}
def triangle() = new Shape{
def sides() = 3
}
Next thing: methods with empty parameter list are generally reading as method that have side effects. So it is more convenient to define your type like
sealed trait Shape{
def sides:Int
}
and if you define your builders like
def square = new Shape{
def sides = 4
}
def triangle = new Shape{
def sides = 3
}
you should use them as someFunction(square _) telling, that you gonna use method call and not the value it's returning
And last thing is: if you really need the code, that creates some object, but it could contain complex computations, resource handling or some probable exception, so you want to hold over it's execution until it' really needed, you could use call-by-name parameters which is equivalent to R , which i assume you are familiar with
Unless shape has an apply function, you cannot call () on a shape object.
If you want to assign aShape to a, simply write val aShape = a.
But since I do not see the added value, you might as well call the sides function directly on a:
def someFunction(a:shape) = {
val sides = a.sides
// use sides
}
This is the closest translation for what you wrote:
sealed trait Shape {
def sides: Int
}
case object Square extends Shape {
override val sides = 4
}
case object Triangle extends Shape {
override val sides = 3
}
def someFunction(a: Shape) =
val shapeSides = a.sides
Some notes:
Classes in scala should be CamelCase
Your subclasses have no instance members, so you can use a singleton object
You if you have a: Shape it means that a is a Shape, and you haven't defined anything that would let you call () on it.
You can omit braces when there's only one expression inside
You can override a def with val if it's static
I am currently learning Scala and I am reading (from cover to cover) Martin Ordesky's book. In chapter 10 I found this:
Great I both understand and like this. So I tried an example:
class Father {
def x = 1 // Method
}
class Child extends Father {
override val x = 1; // Field
}
However, if you try to override an attribute with a method:
class Father {
val x = 1; // Field
}
class Child extends Father {
override def x = 1 // Method
}
I get a compiler error:
method x needs to be a stable, immutable value
override def x = 1
It doesn't work neither if x in Father is var:
method x cannot override a mutable variable
override def x = 1
So we have two cases (and my two questions):
Trying to override an inmutable field: Is this forbidden in order to guarantee x won't be overriden by a method whose value changes over time? Is there any other reason?
Trying to override a mutable field: Why can't a mutable field be overriden? I initially thought that it is to avoid class users assigning values to parameterless methods but then no parameterless method should be allowed.
Allowing overriding of a val by a def would require going through lots of hoops in the generated constructor, and there would be redundant fields in subclasses. It's technically possible to implement this but there are no benefits.
Allowing overriding of a var by a def wouldn't make sense. What would assigning to it mean?
Assuming that I have a Scala case class like the following:
case class Item(
roundedValue: Double = 0.00)
I want to perform the following rounding operation on roundedValue every time the variable is updated:
roundedValue = math.round(roundedValue*100)*0.01
In other languages I would just override the setter for roundedValue, but it appears that I cannot override the setter for a case class variable or it won't compile.
One solution I have seen is to rename roundedValue to _roundedValue and make it private, and then add public methods to simulate getter and setter (with rounding logic): Overriding setter on var
However this makes constructor usage pretty awkward for the case class when using named parameters. Is there any other way to do this, or is this a limitation of case classes in Scala?
If you can make it work, I would recommend keeping your case class immutable, but making a "copy" method that does your mutations on a new instance.
case class Item(roundedValue: Double = 0.0) {
def withValue(newValue: Double) = Item(math.round(newValue*100)*0.01)
}
You may also/instead want to have a similar method in the companion object:
object Item {
def withValue(value: Double) = Item(math.round(roundedValue*100)*0.01)
}
I have an parent class, and several child classes. What I want is when specific setter methods are called on instances of the child classes, a boolean value for "is synchronized" in the parent class is set to false. It should be possible to create child classes in either a synchronized or an unsynchronized state.
This is what I came up with:
class A(protected var isSync: Boolean) {
}
class B(var value:String, isSync: Boolean) extends A(isSync) {
override def value_=(value:String): Unit = {
this.isSync = false
this.value = value
}
}
Now, this doesn't compile for a number of reasons: the assignment of value to this.value is ambiguous; the var annotation already defines value_=; and this.isSync references the local constructor field isSync, instead of the (writable) parent field.
This question on Stack Overflow pointed out that I should use __value (or any name that isn't value) as a private var in the constructor, and define the setter myself. After some more tinkering, I came up with the following code that compiles and works:
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, private val __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
However, this code feels so rancid that by now I suspect I'm making a (if not more) fundamental mistake. Could anyone please correct me?
Thus the concrete questions are:
Are there (and if, which) fundamental flaws in what I'm trying to implement? For some context: the objects, when changed, can (and probably have to) be synchronized with a server.
What is the right/best way to pass parameters to a class you extend?
What is the right/best way to override the setter generated by var (or generally provide your own setter implementation)?
About question 1: I guess that you want to track whether the object has been changed since last time it was copied to the server, don't you? That's sensible, as long as the copy on the server cannot be modified: otherwise ensuring consistency of the replica is more complex (replica consistency is the keyword for googling, but I wouldn't recommend it).
For clarity, I would talking about being clean or dirty - synchronized reminds me too closely of the synchronized Java statement.
About question 2, you don't need to make __isSync a private val (which will be stored in the class), you can leave it as a constructor parameter. As long as it is not used (other than in the invocation of A's constructor) __isSync should not take additional space in instances of B. I removed the private val annotation there, obtaining this code which compiles correctly as expected.
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
About aesthetics and question 3: I would simply avoid the double underscore. Similar examples from Programming in Scala (Sec 18.2) simply use shorter names. They also use private[this] to prevent access to the member from other instances of the same class. Finally, you can remove {} after the class decl. in this example (even if maybe not in your code).
Thus we'd get code like this, which is close to the examples I already mentioned:
class A(protected var isSync: Boolean)
class B(private[this] var v: String, sync: Boolean)
extends A(sync) {
def value = v
def value_=(value: String) = {
isSync = false
v = value
}
}
I know that objects are treated pretty much like singletons in scala. However, I have been unable to find an elegant way to specify default behavior on initial instantiation. I can accomplish this by just putting code into the body of the object declaration but this seems overly hacky. Using an apply doesn't really work because it can be called multiple times and doesn't really make sense for this use case.
Any ideas on how to do this?
Classes and objects both run the code in their body upon instantiation, by design. Why is this "hacky"? It's how the language is supposed to work. If you like extra braces, you can always use them (and they'll keep local variables from being preserved and world-viewable).
object Initialized {
// Initalization block
{
val someStrings = List("A","Be","Sea")
someStrings.filter(_.contains('e')).foreach(s => println("Contains e: " + s))
}
def doSomething { println("I was initialized before you saw this.") }
}
scala> Initialized.doSomething
Contains e: Be
Contains e: Sea
I was initialized before you saw this.
scala> Initialized.someStrings
<console>:9: error: value someStrings is not a member of object Initialized
Initialized.someStrings
Rex has it right, I just wanted to point out a pattern I use a lot, that saves you from having to use vars, while avoiding namespace pollution by intermediate values.
object Foo {
val somethingFooNeeds = {
val intermediate = expensiveCalculation
val something = transform(intermediate)
something
}
}
If it makes you feel better, you can create some class with protected constructor and object will create singleton of this class:
sealed class MyClass protected (val a: String, b: Int) {
def doStuff = a + b
}
object MyObject extends MyClass("Hello", b = 1)
Also notice, that sealed stops other classes and objects to extend MyClass and protected will not allow creation of other MyClass instances.
But I personally don't see any problems with some code in the body of the object. You can also create some method like init and just call it:
object MyObject {
init()
def init() {
...
}
}
The body of object and class declarations IS the default constructor and any code placed in there will be executed upon first reference, so that is exactly the way to do it.