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)
}
Related
The code below gives a compile error:
class Info(val x: String)
object Info {
val default = new Info("top")
}
case class Data(x: String) {
import Info.default
def this() = this(default.x)
}
Error:(11, 23) not found: value default
def this() = this(default.x)
Why is symbol default not seen in the constructor, in spite of the import?
Further experiments show it is not only import. Replacing import line with a def (or even val) does not help, still the error persists:
def default = Info.default
Scoping doesn't work the way you expected because of the scoping of self constructor invocations (when secondary constructors invoke the primary constructor):
The signature and the self constructor invocation of a constructor
definition are type-checked and evaluated in the scope which is in
effect at the point of the enclosing class definition, augmented by
any type parameters of the enclosing class and by any early
definitions of the enclosing template.
In other words, the scope in effect for the expression default.x is the scope outside Data.
This is confusing because textually it looks like that expression is inside the class.
This rule has to do with lexical scope and not with evaluation order.
You have to move the import outside the class definition.
For fun, scoping is slightly broken in the following case:
object Playroom {
def default = "playing"
case class Toy(squeezeMsg: String = default)
object Toy {
def default = "srsly"
}
}
object Test extends App {
import Playroom._
println(Toy())
println(new Toy())
}
which is this puzzler. Generally speaking, it's more idiomatic (and robust) to use apply methods on the companion.
This is behaving according to specs. The body of the class is part of the so called primary constructor. The auxiliary constructor(s) needs to start by calling the primary or another auxiliary defined before. Assuming you only have one auxiliary, since the call to primary must be the first statement in your auxiliary, it means that during this first statement you do not have access to anything defined inside the primary. After the first call is done, then you can access any of the members and imports defined in the primary.
In your example, the problem is that the import (import Info.default) is not visible to the first statement of your auxiliary. If you replace it with def this() = this(Info.default.x) it should work.
Example:
The following compiles fine since the call to Constant is done after the call to the primary.
class G(i: Int) {
val Constant = 1
// No argument auxiliary constructor
def this() = {
this(3) // Call to primary
println(Constant * 2)
}
}
The following does not compile since the call to Constant is done before the call to the primary, which means that Constant has not been created yet.
class G(i: Int) {
val Constant = 1
// No argument auxiliary constructor
def this() = {
this(Constant) // This will cause an error!
}
}
Solution:
Have any constants you need defined in the companion object. The companion object is by definition initialized first, so you will be able to access any members of it from within the constructors of your class.
object G {
val Constant = 1
}
class G(i: Int) {
// No argument auxiliary constructor
def this() = {
this(G.Constant) // This now works!
}
}
In scala, any fields defined in the class is not available until after the primary constructor is invoked. To fix it is usually used companion object with apply method.
I haven't been able to find anything in the language definition that explains the initialisation of a class in Kotlin.
import java.util.Properties
fun main(args: Array<String>) {
val out = MyClass()
out.fn()
}
class MyClass {
private val a = Properties() // 1
init {
fn()
}
public fun fn() {
println("Fn called. a = $a")
}
// private val a = Properties() // 2
}
The results of running this program change depending whether the property is initialised at (1) or at (2).
I'm surprised that the declaration order is relevant in the language and would like to understand the decisions behind this. My expectation would be that properties are initialised before the constructor body is invoked.
My expectation would be that properties are initialised before the constructor body is invoked.
Well, init block is not a constructor. It is a different construct which allows you to perform the initialization of the object and they [init blocks] are performed in the declaration order with the property initializers.
Constructors are a different beast ant they are performed after all the properties were initialized and all init blocks were performed. Look at the following example:
class A(val value: Int) {
constructor(): this(0) {
println("Constructor")
}
init {
println("Init block")
}
}
fun main(args: Array<String>) {
val a = A()
}
Output is:
Init block
Constructor
You can place the init block wherever you want: before the constructor or after it; it will always be performed before the A's constructor (secondary constructor, in this example).
Simply put: when an instance of a class is created, (almost) firstly runs the constructor of the parent class (if present), then the primary constructor.
The primary constructor executes code declared in the class body from the top to the bottom. Also the names became available by the same rule:
class Foo(a: String = "might be first"
val b: String = "second" + a) : Boo(a + b + "third"){
var c = a + "fourth" + b
init {print("fifth: $c")}
val d = "sixth"
init {print("seventh: the end of the primary constructor"}
}
If you invoke a secondary constructor, then it works after the primary one as it is composed in the chain (similar to invoking the parent constructors).
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?
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.
I'm working on an automatic mapping framework built on top of Dozer. I won't go into specifics as it's not relevant to the question but in general it's supposed to allow easy transformation from class A to class B. I'd like to register the projections from a class's companion object.
Below is a (simplified) example of how I want this to work, and a Specs test that assures that the projection is being registered properly.
Unfortunately, this doesn't work. From what I can gather, this is because nothing initializes the A companion object. And indeed, if I call any method on the A object (like the commented-out hashCode call, the projection is being registered correctly.
My question is - how can I cause the A object to be initialized automatically, as soon as the JVM starts? I don't mind extending a Trait or something, if necessary.
Thanks.
class A {
var data: String = _
}
class B {
var data: String = _
}
object A {
projekt[A].to[B]
}
"dozer projektor" should {
"transform a simple bean" in {
// A.hashCode
val a = new A
a.data = "text"
val b = a.-->[B]
b.data must_== a.data
}
}
Short answer: You can't. Scala objects are lazy, and are not initialized until first reference. You could reference the object, but then you need a way of ensuring the executing code gets executed, reducing the problem back to the original problem.
In ended up doing this:
trait ProjektionAware with DelayedInit
{
private val initCode = new ListBuffer[() => Unit]
override def delayedInit(body: => Unit)
{
initCode += (() => body)
}
def registerProjektions()
{
for (proc <- initCode) proc()
}
}
object A extends ProjektionAware {
projekt[A].to[B]
}
Now I can use a classpath scanning library to initialize all instances of ProjektionAware on application bootstrap. Not ideal, but works for me.
You can force the instantiation of A to involve the companion object by using an apply() method or some other sort of factory method defined in the object instead of directly using the new A() constructor.
This does not cause the object to be initialized when the JVM starts, which I think as noted in another answer can't generally be done.
As Dave Griffith and Don Roby already noted, it cannot be done at JVM startup in general. However maybe this initialization could wait until first use of your framework?
If so, and if you don't mind resorting to fragile reflection tricks, in your --> method you could obtain reference to the companion object and get it initialize itself.
You can start at Getting object instance by string name in scala.
We could use this sort of a way to ensure that companion object gets initialized first and then the class gets instantiated.
object B {
val i = 0
def apply(): B = new B()
}
class B {
// some method that uses i from Object B
def show = println(B.i)
}
// b first references Object B which calls apply()
// then class B is instantiated
val b = B()