What are the Kotlin class initialisation semantics? - class

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).

Related

How to qualify methods as static in Scala?

I have a class
class MyClass {
def apply(myRDD: RDD[String]) {
val rdd2 = myRDD.map(myString => {
// do String manipulation
}
}
}
object MyClass {
}
Since I have a block of code performing one task (the area that says "do String manipulation"), I thought I should break it out into its own method. Since the method is not changing the state of the class, I thought I should make it a static method.
How do I do that?
I thought that you can just pop a method inside the companion object and it would be available as a static class, like this:
object MyClass {
def doStringManipulation(myString: String) = {
// do String manipulation
}
}
but when I try val rdd2 = myRDD.map(myString => { doStringManipulation(myString)}), scala doesn't recognize the method and it forces me to do MyClass.doStringManipulation(myString) in order to call it.
What am I doing wrong?
In Scala there are no static methods: all methods are defined over an object, be it an instance of a class or a singleton, as the one you defined in your question.
As you correctly pointed out, by having a class and an object named in the same way in the same compilation unit you make the object a companion of the class, which means that the two have access to each others' private fields and methods, but this does not mean they are available without specifying which object you are accessing.
What you want to do is either using the long form as mentioned (MyClass.doStringManipulation(myString)) or, if you think it makes sense, you can just import the method in the class' scope, as follows:
import MyClass.doStringManipulation
class MyClass {
def apply(myRDD: RDD[String]): Unit = {
val rdd2 = myRDD.map(doStringManipulation)
}
}
object MyClass {
private def doStringManipulation(myString: String): String = {
???
}
}
As a side note, for the MyClass.apply method, you used the a notation which is going to disappear in the future:
// this is a shorthand for a method that returns `Unit` but is going to disappear
def method(parameter: Type) {
// does things
}
// this means the same, but it's going to stay
// the `=` is enough, even without the explicit return type
// unless, that is, you want to force the method to discard the last value and return `Unit`
def method(parameter: Type): Unit = {
// does things
}
You should follow scala's advice.
val rdd2 = myRDD.map(MyClass.doStringManipulation)
Write this inside the class then it will work as expected.
import MyClass._

Why does auxiliary constructor not see import done in the class?

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.

Scala, class using mutable var, update in overriding method

I am having a hard time understanding how to get the following code structure to work.
In Scala I have a class MyClass which inherits from SomeClass I added a var member variable in this case called mutableArray and it is being updated in the overridden method overridingSomeClassMethod and is called when I create a new instance of the MyClass a number of times right away. But in main when I try and get the updated mutableArray variable it prints out the instantiated var as if it is immutable or only has scope in the overriding method.
I can't change the method in parent SomeClass, and I tried creating a companion object as well as putting the variable in the encompassing SomeOtherObject but I get the same exact issue.
import scala.collection.mutable.ArrayBuffer
object SomeOtherObject{
case MyClass(...) extends SomeClass(..){
var mutableArray: ArrayBuffer[Int] = ArrayBuffer.fill(5)(0)
def overridingSomeClassMethod(...){
var someReturnVar = 0.0
mutableArray(0) += 1
println(mutableArray.mkString) // last output -> 84169
someReturnVar
}
}
def main(args: Array[String]){
var mc = new MyClass
println(mc.mutableArray.mkString) // output -> 00000
}
}
You can use an early initializer:
case MyClass(...) extends {
var mutableArray: ArrayBuffer[Int] = ArrayBuffer.fill(5)(0)
} with SomeClass(..) {
Probably you are hitting the infamous "one question FAQ" about initialization order.
If the method is invoked by the superclass constructor, then your initialization happens after that, resetting the data to zero.

Force initialization of Scala singleton object

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()

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)
}