Rationale for behaviour overriding a val - scala

class A {
val x = println("A")
}
class B extends A {
override val x = println("B")
}
(new B).x
Prints:
A
B
However,
class A {
lazy val x = println("A")
}
class B extends A {
override lazy val x = println("B")
}
(new B).x
Prints just:
B
According to Martin Odersky, the behaviour, at least in the non-lazy case, is "as specified". I'm curious as to why the behaviour is specified that way, and why it differs when the val is lazy.

The code in the template ("body") of a class definition, outside of member definitions, is what goes into the constructor. Constructors for parent classes are always called when you initialize an instance of a child class (in this case, you are calling a constructor with no arguments, otherwise the syntax would be class B extends A(arg1, arg2) { ... }). For more details, see Section 5.1 in the Scala Language Specification.
That is why println("A") is evaluated in the first case; that val definition is part of the constructor code.
When you think about what happens at construction time in the second example, you never asked for the value of x defined in A; now because it is a lazy val, it will not be computed before it is needed.
You can think of lazy vals as methods that take no argument and that cache their output the first time they are called. You didn't call that method here, you just defined it.

class A {
val x = println("A")
}
class B extends A {
override val x = println("B")
}
(new B).x
During the execution of the constructor, all the initializations of vals (and other statements) are executed. Therefore, val x = println("A") is run as part of the construction of A and override val x = println("B") is run as part of the construction of B. They both print some string and initialize x to () (of type Unit), so override is just a red herring here. The .x (from (new B).x) does nothing.
In the lazy case, you're initializing x to something like a function taking no arguments and returning Unit. It is not run till you read .x, and, since x is overridden, only "B" gets printed in that case.

Related

Can't understand path dependent type

For a class C, you can use the familiar this inside the body to refer to the current instance, but this is actually a shorthand for C.this in Scala:
class C {
var x = "1"
def setX1(x:String) = this.x = x
def setX2(x:String) = C.this.x = x
}
I just can't understand C.this, C is a class, I can't understand why we use dot between C and this as shown in C.this?
I can't understand why we use dot between C and this as shown in
C.this
Using the class name before this is called a Qualified this in Java (see Using "this" with class name) and is similar in Scala. You use it when you want to reference an outer class from an inner class. Let's assume for example that you had a method declaration in your C class where you wanted to call this and mean "the this reference of C:
class C {
val func = new Function0[Unit] {
override def apply(): Unit = println(this.getClass)
}
}
new C().func()
Yields:
class A$A150$A$A150$C$$anon$1
You see the anon$1 at the end of the getClass name? It's because inside the function instance this this is actually of the function class. But, we actually wanted to reference the this type of C instead. For that, you do:
class C {
val func = new Function0[Unit] {
override def apply(): Unit = println(C.this.getClass)
}
}
new C().func()
Yields:
class A$A152$A$A152$C
Notice the C at the end instead of anon$1.

Create proper late initialization of an abstract val in trait

Consider the following case:
trait A {
protected val mydata = ???
def f(args) = ??? //uses mydata
}
class B
class C
class D(arg1: String) extends B with A {
override val mydata = ??? /// some calculation based on arg1
}
class E(arg1: String) extends C with A{
override val mydata = ??? /// some calculation based on arg1
}
A must be a trait as it is used by different unrelated classes. The problem is how to implement the definition of mydata.
The standard way (suggested in many places would be to define mydata as def and override it in the children. However, if f assumes mydata never changes then it can cause issues when some child extends with a function which changes between calls instead of with a val.
Another way would be to do:
trait A {
protected val mydata = g
protected def g()
}
The problem with this (beyond adding another function) is that if g depends on construction variables in the child then these must become members of the child (which can be a problem for example if the data is large and given in the construction):
class D(arg1: Seq[String]) {
def g() = ??? // some operation on arg1
}
If I leave the val in the trait as abstract I can reach issues such as those found here).
What I am looking for is a way to define the value of the val in the children, ensuring it would be a val and without having to save data for late calculations. Something similar as to how in java I can define a final val and fill it in the constructor
The standard way (suggested in many places would be to define mydata as def and override it in the children... If I leave the val in the trait as abstract I can reach issues such as those found here).
This is a common misunderstanding, shown in the accepted answer to the linked question as well. The issue is implementing as a val, which you require anyway. Having a concrete val which is overridden only makes it worse: abstract one can at least be implemented by a lazy val. The only way to avoid the issue for you is to ensure mydata is not accessed in a constructor of A or its subtypes, directly or indirectly, until it's initialized. Using it in f is safe (provided f is not called in a constructor, again, which would be an indirect access to mydata).
If you can ensure this requirement, then
trait A {
protected val mydata
def f(args) = ??? //uses mydata
}
class D(arg1: String) extends B with A {
override val mydata = ??? /// some calculation based on arg1
}
class E(arg1: String) extends C with A{
override val mydata = ??? /// some calculation based on arg1
}
is exactly the correct definition.
If you can't, then you have to live with your last solution despite the drawback, but mydata needs to be lazy to avoid similar initialization order issues, which would already give the same drawback on its own.

proper use of scala traits and types

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

Implementing '.clone' in Scala

I'm trying to figure out how to .clone my own objects, in Scala.
This is for a simulation so mutable state is a must, and from that arises the whole need for cloning. I'll clone a whole state structure before moving the simulation time ahead.
This is my current try:
abstract trait Cloneable[A] {
// Seems we cannot declare the prototype of a copy constructor
//protected def this(o: A) // to be defined by the class itself
def myClone= new A(this)
}
class S(var x: String) extends Cloneable[S] {
def this(o:S)= this(o.x) // for 'Cloneable'
def toString= x
}
object TestX {
val s1= new S("say, aaa")
println( s1.myClone )
}
a. Why does the above not compile. Gives:
error: class type required but A found
def myClone= new A(this)
^
b. Is there a way to declare the copy constructor (def this(o:A)) in the trait, so that classes using the trait would be shown to need to provide one.
c. Is there any benefit from saying abstract trait?
Finally, is there a way better, standard solution for all this?
I've looked into Java cloning. Does not seem to be for this. Also Scala copy is not - it's only for case classes and they shouldn't have mutable state.
Thanks for help and any opinions.
Traits can't define constructors (and I don't think abstract has any effect on a trait).
Is there any reason it needs to use a copy constructor rather than just implementing a clone method? It might be possible to get out of having to declare the [A] type on the class, but I've at least declared a self type so the compiler will make sure that the type matches the class.
trait DeepCloneable[A] { self: A =>
def deepClone: A
}
class Egg(size: Int) extends DeepCloneable[Egg] {
def deepClone = new Egg(size)
}
object Main extends App {
val e = new Egg(3)
println(e)
println(e.deepClone)
}
http://ideone.com/CS9HTW
It would suggest a typeclass based approach. With this it is possible to also let existing classes be cloneable:
class Foo(var x: Int)
trait Copyable[A] {
def copy(a: A): A
}
implicit object FooCloneable extends Copyable[Foo] {
def copy(foo: Foo) = new Foo(foo.x)
}
implicit def any2Copyable[A: Copyable](a: A) = new {
def copy = implicitly[Copyable[A]].copy(a)
}
scala> val x = new Foo(2)
x: Foo = Foo#8d86328
scala> val y = x.copy
y: Foo = Foo#245e7588
scala> x eq y
res2: Boolean = false
a. When you define a type parameter like the A it gets erased after the compilation phase.
This means that the compiler uses type parameters to check that you use the correct types, but the resulting bytecode retains no information of A.
This also implies that you cannot use A as a real class in code but only as a "type reference", because at runtime this information is lost.
b & c. traits cannot define constructor parameters or auxiliary constructors by definition, they're also abstract by definition.
What you can do is define a trait body that gets called upon instantiation of the concrete implementation
One alternative solution is to define a Cloneable typeclass. For more on this you can find lots of blogs on the subject, but I have no suggestion for a specific one.
scalaz has a huge part built using this pattern, maybe you can find inspiration there: you can look at Order, Equal or Show to get the gist of it.

Scala 2.8: how to initialize child class

Consider the following code:
abstract class X {
def a:Unit
a
}
class Y extends X {
var s:String = "Hello"
def a:Unit = println ("String is "+s)
}
This gives the following output:
scala> new Y
String is null
res6: Y = Y#18aeabe
How can I get the parent class X to wait for s to be initialized when calling a
The parent's fields and the parent constructor are always initialized and run before the children's field and constructor. It means that the call to a happens before your var s is set in the child class.
In general, it's a bad idea to call a virtual method from a constructor; C++ even disallows it (or, rather than disallowing it, doesn't call the method implemented in the child class when called from the superclass's constructor).
However, you can fix it if you turn your var s in class Y into a lazy val or a def instead. lazy vals are initialized the first time their value is accessed, no matter by whom; defs pose no initialization issues like vars or vals. However, be careful not to call any other uninitialized structure from within the implementation of a, as the same problem will show up again.
Edit:
You can also use Scala's “early definitions” (or early initialization) feature:
class Y extends {
var s = "Hello"
} with X {
def a: Unit = println ("String is "+s)
}