Init method inheritance - kotlin

If I have abstract class A with an init method:
abstract class A(){
init {
println("Hello")
}
}
And then class B that extends A
class B(): A()
If I instantiate B like this
fun main(args: Array<String>){
B()
}
Does the init method in A still get run and Hello gets printed?
And if not, what do I need to do to have the init method of A get run?

Yes, an init block of a base class gets run when the derived class instance is initialized.
In Kotlin, similarly to Java, an instance of a class is constructed in the following way:
An object is allocated.
The constructor of the class is called. (a)
If the class has a superclass, the superclass constructor is called before the class construction logic is executed; (i.e., the point (a) is executed recursively for the superclass, then the execution continues from here)
If the class has property initializers or init blocks, they are executed in the same order as they appear in the class body;
If the constructor has a body (i.e. it is a secondary constructor) then the body is executed.
In this description, you can see that, when B is constructed, the constructor of A is called before B initialization logic is executed, and, in particular, all init blocks of A are executed.
(runnable demo of this logic)
A small remark on terminology: init block is not actually a separate method. Instead, all init blocks together with member property initializers are compiled into the code of the constructor, so they should rather be considered a part of the constructor.

Related

What's an example of using an overridden property in the Base Class initialization (either directly or indirectly)?

It means that, by the time of the base class constructor execution, the properties declared or overridden in the derived class are not yet initialized. If any of those properties are used in the base class initialization logic (either directly or indirectly, through another overridden open member implementation), it may lead to incorrect behavior or a runtime failure. When designing a base class, you should therefore avoid using open members in the constructors, property initializers, and init blocks.
I was studying Inheritence from Kotlin docs, and I got stuck here. There was another post which asked a question about this, but the answers were just what the docs said in a different way.
To be clear, I understood the data flow between constructors and inheritence. What I couldn't understand was how we can use an overridden property in a base class initialization. It says
It could happen directly or indirectly
  What does this actually mean? How can the base class can somehow access to the overridden property in the derived class?
Also, it said
You should therefore avoid using open members in the constructors,
property initializers and init blocks.
 So how can we properly use open properties?
EDIT FOR THE COMMENT:
fun main ()
{
val d = Derived("Test2")
}
open class Base()
{
open val something:String = "Test1"
init
{
println(something) //prints null
}
}
class Derived(override val something: String): Base()
What does this actually mean? How can the base class can somehow access to the overridden property in the derived class?
This is one direct way:
abstract class Base {
abstract val something: String
init {
println(something)
}
}
class Child(override val something: String): Base()
fun main() {
Child("Test") // prints null! because the property is not initialized yet
}
This prints null, which is pretty bad for a non-nullable String property.
You should therefore avoid using open members in the constructors, property initializers and init blocks.
So how can we properly use open properties?
You can use these properties in regular methods on the base class (or in custom property getters):
abstract class Base {
abstract val something: String
fun printSomething() {
println(something)
}
}
class Child(override val something: String): Base()
fun main() {
Child("Test").printSomething() // correctly prints "Test"
}
EDIT: Here are some clarifications regarding the follow-up questions in the comments.
I couldn't quite get why the code in the init block went for the parameter in the child class constructor
I think you might be confused by Kotlin's compact syntax for the primary constructors in general, which probably makes the debugger's flow hard to understand. In the Child declaration, we actually declare many things:
the argument something passed to the Child's primary constructor
the property something on the Child class, which overrides the parent's one
the call to the parent constructor (Base())
When Child() is called, it immediately calls the Base() no-arg constructor, which runs the init block.
We didn't even delegate the base constructor with a parameter or anything, but it still went for the parameter who did the overriding
You might be mixing declarations and runtime here. Although we declare things in the Base class and in the Child class, there is only 1 instance at runtime (an instance of Child) in this example code.
So, in fact, there is only 1 property called something here (only one place in memory). If the init block accesses this property, it can only be the property of the child instance. We don't need to pass anything to the Base constructor because the init block is effectively executed with the data/fields of the Child instance.
Maybe you would be less confused if you saw the Java equivalent of this. It's obvious if you think of the abstract something as a declaration of a getter getSomething(). The child class overrides this getSomething() method and declares a private something field, the getter returns the current value of the field something. But that field is only initialized after the constructor of the parent (and the init block) finished executing.

Why would you use a Kotlin companion object rather than an initializer block for creation?

#37 Kotlin Tutorial | Companion Object | Factory Pattern says you can use a Kotlin companion object when creating a class when it is complicated.
Kotlin Primary Constructor and Initializer Blocks shows how to use a Kotlin initializer block in a class.
fun main(args: Array<String>) {
val person1 = Person("joe", 25)
}
class Person(fName: String, personAge: Int) {
val firstName: String
var age: Int
// initializer block
init {
firstName = fName.capitalize()
age = personAge
println("First Name = $firstName")
println("Age = $age")
}
}
Why would you use the companion object to do this rather than the initializer block?
Regarding this question, I have no interest in Java.
This practice of considering static factory methods (aka companion objects in Kotlin) over constructors (or init blocks in Kotlin) has been borrowed from the Java world.
The differences between static factory methods and constructors in Java are pretty much the same as the differences between companion objects and init blocks in Kotlin.
Here's a Medium article which describes the advantages of companion objects neatly. To summarize:
Unlike constructors, they have names
Unlike constructors, they do not require to create a new object each time they’re invoked
Unlike constructors, they can return an object of any subtype of their return type
They reduce verbosity of creating parameterized type instances
EDIT: Added AjahnCharles' comment as it's a valid use-case.
They can return a null object, thereby indicating invalid params being passed for creating the object. ()
As with all design patterns, there are also disadvantages with companion objects:
They cannot be used in subclasses construction
They are not readily distinguishable from other static methods
The general idea behind factory methods is that you have some input to the factory method, execute some logic, and then have "output" that is the necessary parameters for the object constructor.
When you have only a single factory method, the main advantage of using it is that it lets your class expose only a single primary constructor that shows everything your class needs and everything your class retains. The logic to derive all of these properties is elsewhere. I personally think that this is nice, but it is admittedly not an extremely strong reason to prefer a factory method.
However, as soon as you have two different factory methods, the plan of using an initializer block becomes impossible. Even if you create a secondary constructor, any constructor of your class will execute all init blocks... so there's no way to have two "separate" factories using initializers.
The following is a very contrived example, but it does demonstrate behavior that would be impossible with only constructors and init blocks:
class Example(val text: String) {
companion object {
fun firstFactory(): Example {
println("you called the first factory method")
return Example("first")
}
fun secondFactory(): Example {
println("you called the second factory method")
return Example("second")
}
}
}

Instantiating an object within the object declaration in kotlin

While browsing through kotlin documentation at object expressions and declarations I came across this snippet
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
val instance = MyClass.create()
In line 3, the create function instantiates an object MyClass()
In last line however, to call the create we already need MyClass object (don't we?).
My question is: At what point does the MyClass comes into existence?
The invocation val instance = MyClass.create() is independent of an instance of MyClass, you simply use the type as a qualifier for the method (it's like static methods in Java). Note that you can also write MyClass.Factory.create(), the companion's name is redundant when calling it from Kotlin though.
In last line however, to call the create we already need MyClass object (don't we?).
No, the last line calls .create() on the companion object of MyClass. The companion object is an instance of a separate class (it is not MyClass) and is initialized before the class is first used, so you don't need an instance of MyClass to call .create().
Note that, syntactically, .create() is called on the MyClass class name, not on an ordinary exppression like MyClass() constructor call or a myClass variable.

Kotlin Init Block in Super class firing with null properties when inheriting from it

open class Super {
open var name : String = "Name1"
init {
println("INIT block fired with : $name")
name = name.toUpperCase()
println(name)
}
}
class SubClass(newName : String) : Super() {
override var name : String = "Mr. $newName"
}
fun main(args: Array<String>) {
var obj = SubClass("John")
println(obj.name)
}
The above Kotlin code results in the following TypeCastException :
INIT block fired with : null
Exception in thread "main" kotlin.TypeCastException: null cannot be cast to non-null type java.lang.String
at Super.<init>(index.kt:7)
at SubClass.<init>(index.kt:13)
at IndexKt.main(index.kt:21)
As my understanding goes while inheriting from a class in Kotlin, first the primary constructors and init blocks and secondary constructors of super classes are called with passed parameters. After which the subclass can override such properties with its own version.
Then why does the above code results in the exception as described ... What am I doing wrong ... Why does the init block in super class is fired with null ...??? At first my speculation was that the init block might get fired before the actual property initialization as it is executed as a part of primary constructor but initializing the name property in the primary constructor as below gives the same error and the IDE would have warned me if so.
open class Super(open var name : String = "Name1") {
init {
println("INIT block fired with : $name")
name = name.toUpperCase()
println(name)
}
}
class SubClass(newName : String) : Super() {
override var name : String = "Mr. $newName"
}
fun main(args: Array<String>) {
var obj = SubClass("John")
println(obj.name)
}
Console :
INIT block fired with : null
Exception in thread "main" kotlin.TypeCastException: null cannot be cast to non-null type java.lang.String
at Super.<init>(index.kt:5)
at Super.<init>(index.kt:1)
at SubClass.<init>(index.kt:11)
at IndexKt.main(index.kt:19)
Am I doing something wrong here or is this a language bug...??? What can I do to avoid the error and to make the init blocks fire with the actual passed value and not null ... ??? Elaborate what is happening behind the scene. At this time I have several situations with classes like this in my actual codebase where I want to inherit from another classes, I want to maintain property names as they are...
Essentially, because you tell Kotlin that your subclass is going to be defining name now, it is not defined when the init block in Super is executed. You are deferring definition of that until the SubClass is initialized.
This behavior is documented on the Kotlin website under "Derived class initialization order":
During construction of a new instance of a derived class, the base class initialization is done as the first step (preceded only by evaluation of the arguments for the base class constructor) and thus happens before the initialization logic of the derived class is run.
...
It means that, by the time of the base class constructor execution, the properties declared or overridden in the derived class are not yet initialized. If any of those properties are used in the base class initialization logic (either directly or indirectly, through another overridden open member implementation), it may lead to incorrect behavior or a runtime failure. Designing a base class, you should therefore avoid using open members in the constructors, property initializers, and init blocks. [emphasis mine]
FWIW, this is similar to the reason that some Java code analysis tools will complain if you refer to non-final methods in a constructor. The way around this in Kotlin is to not refer to open properties in your init blocks in the superclass.
Have the same trouble, a disgusting issue with kotlin, when subclass constructor is ignored or initialized after super class calls internal method, this is not a safe thing, if not worst i found in kotlin.

SCJP v6 (Sierra,Bates) Chapter 2, Question 12 Interpretations of constructor calls

Could I have some feedback on this
Given "new House("x ")" sends a string I had expected that the "House(String name)" constructor would have called the Building super class constructor "Building(String name)". In which case the answer would have been "bn x h hn x". However the answer is "b h hn x" (and yes it does run with that output).
Questions
1. Other than a call "new Building("string_value")" would there be a situation when House would call the "Building(String name)" constructor? (ie other than additional code in the House constructors?
2.Why is it that the no argument Building constructor is called, rather than the overloaded Building (String name) constructor? What I am looking is a possibility there could be many Building constructors and there could be a need to call specific super constructors from subclasses. How do you ensure which constructor (given two or more choices) is called?
Code included for ease of reference.
The answer is "b h hn x"
class Building {
Building() {System.out.print("b ");}
Building(String name) {this(); System.out.print("bn "+name);}
}
public class House extends Building {
House() {System.out.print("h ");}
House(String name) { this();System.out.print("hn "+name);}
public static void main(String a[]) {
new House("x "); }
}
Regards
Scott
If no explicit superclass constructor call is provided, and no call to a constructor in the same class is provided either, the no-args superclass constructor is always called. That's how Java is designed, and it would be too complicated and inefficient for the JVM to record which was the first constructor called and try and match it up with a superclass constructor.
If you needed to call a different superclass constructor, you would just call it explicitly, like this:
super(foo,bar);
When inheriting from another class, you must call super() in your constructor. If you don't, the compiler will insert that call for you as you can plainly see.
The superclass constructors are called because otherwise the object would be left in an uninitialized state.
Your program execution order is given below:
new House("x "); // call in main this will call same class default constructor because of this(), as you knew already that first statement must be either this() or super() if any
Call to this() in above constructor executes House() constructor. Now in House() there is no this() call so compiler puts default super() which will call base class default constructor and
hence the output is b h hn x