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

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.

Related

Kotlin: referring to delegate that is not passed by constructor

I want to use Kotlin delegation in a particular context.
The delegate should not be passed in the constructor.
I want to keep a reference to the delegate for later use in the code. From within the method that I override, say printMessage(), I still need to call the delegate the same way you'd call super.printMessage() in polymorphic inheritance.
I can do the first by simply instantiating an anonymous delegate in the by clause (class Derived() : Base by BaseImpl(42) using Kotlin's documentation example). However,
this prevents me from accessing the anonymous delegate, as there is no way that I know to reference it.
I want to do something similar to the following. The following however doesn't compile with error 'this' is not defined in this context.
class Derived() : Base by this.b {
val b: Base = BaseImpl(42)
override fun printMessage() {
b.printMessage()
print("abc")
}
}
I do need a separate delegate for each instance of my Derived class. So moving b as a global variable is not an option for me.
The closest I got to what I need is with an optional parameter to the constructor. This is not a good option neither, as I don't want to allow the construction of my Derived class with arbitrary delegates.
You can do this using a private primary constructor and a public secondary constructor:
class Derived private constructor(val b: Base) : Base by b {
constructor(): this(BaseImpl(42))
override fun printMessage() {
b.printMessage()
print("abc")
}
}
If you don't need a reference to the delegate, you can also say simply,
class Derived : Base by BaseImpl(42)

learn the syntax for constructors in Kotlin

I am learning Kotlin programming language perfectly. I try to write code in different patterns and try to understand. However, I did not understand the thing. Can you help me, please?
Here it is:
open class Parent {
open val foo = 1
init {
println(foo)
}
}
class Child: Parent() {
override val foo =2
}
fun main() {
Child()
}
In this code, 0 is the output. How will this be?
This is about the order of construction — and is a subtle gotcha that's easy to fall prey to.  (I'm afraid this answer is a bit long, but the issues here are well worth understanding.)
There are a few basic principles colliding here:
Superclass initialisation happens before subclass initialisation.  This includes code in constructors, code in init blocks, and property initialisers: all of that happens for a superclass before any in a subclass.
A Kotlin property consists of a getter method, a setter method (if it's a var), and a backing field (if needed).  This is why you can override properties; it means that the accessor method(s) are overridden.
All fields initially hold 0/false/null before they get initialised to any other value.  (Normally, you wouldn't get to see that, but this is one of those rare cases.  This differs from languages like C where if you don't explicitly initialise a field it can hold random values depending on what that memory was previously used for.)
From the first principle, when you call the Child() constructor, it will start off by calling the Parent() constructor.  That will set the superclass's foo field to 1, and then get the foo property and print it out.  After that, the Child initialisation happens, which in this case is simply setting its foo field to 2.
The gotcha here is that you effectively have two foos!
Parent defines a property called foo, and that gets accessor methods and a backing field.  But Child defines its own property called foo, overriding the one in Parent — that one overrides the accessor methods, and gets its own backing field as well.
Because of that override, when the Parent's init block refers to foo, it calls the getter method which Child overrides, to get the value of Child's backing field.  And that field hasn't been initialised yet!  So, as mentioned above, it's still holding its initial value of 0, which is the value that the Child getter returns, and hence the value that Parent constructor prints out.
So the real problem here is that you're accessing the subclass field before it's been initialised.  This question shows why that's a really bad idea!  As a general rule:
A constructor/initialiser should never access a method or property that could be overridden by a subclass.
And the IDE helps you out here: if you put your code into IntelliJ, you'll see that the usage of foo is marked with the warning ‘Accessing non-final property foo in constructor’.  That's telling you that this sort of problem is possible.
Of course, there are more subtle cases that an IDE might not be able to warn you about, such as if a constructor calls a non-open method that calls an open one.  So care is needed.
There are occasions when you might need to break that rule — but they're very rare, and you should check very carefully that nothing can go wrong (even if someone comes along later and creates a new subclass).  And you should make it very clear in comments/documentation what's going on and why it's needed.
Now, let's with java understand why. In Java, it's impossible to override fields and under the hood in Kotlin is the same. When you override a property, in fact, you override a getter, not a field. For instance, you can override a property that doesn't have a field with a property that has a field. That's totally legal. However, when both a property from a superclass and an overridden property in a subclass have fields, that might lead to unexpected results. Let's see what bytecode is generated for the Kotlin class in my example. As usual, I'll look at the corresponding Java code instead for simplicity.
public class Parent {
private final int foo = 1;
public int getFoo() {return foo;}
public Parent(){
System.out.println(getFoo());
}
}
public final class Child extends Parent {
private final int foo = 2;
public int getFoo() {return foo;}
}
public class Main
{
public static void main (String[] args) {
new Child();
}
}
Note two things here. First, the foo get to is trivial, so a field and a getter correspond to the full property. Then because the property is open and can be overridden in a subclass, its usage inside the class is compiled to a getter code, not a field code. Now, the generated code for the child class. Note that the overridden property in the parent class is also compiled to a field and a getter, and now it's another field. What happens when you create an instance of the child class? At first at the parent constructor is called, the parent constructor initializes the first fulfilled with one. But inside the init section, an overridden getter is called which calls get foo from the child class. Because the field in the child class is not yet initialized, 0 is returned. That's why 0 is printed here.
Please go through following points:
Initializer Blocks i.e. init {} block are called during an instance initialization. They are called after Primary Constructor.
In above code println(foo) is placed inside init block.
Hence, the value which gets printed i.e. 0 in this case, is the value before assignment statement open val foo = 1.
If you want the output to be 1 then make following changes:
open class Parent {
open var foo : Int = 0
init {
foo = 1
println(foo)
}
}
class Child: Parent() {
override var foo =2
}
fun main() {
Child()
}
And lastly, please go through this post. This will help you in getting better understanding of this area.

What is the benefit of having a private constructor and a use a method inside companion object to instantiate a class?

I've bumped into this code and I'm not sure why would anyone do this. Basically the author decided for making the class constructor private so that it cannot be instantiated outside the file, and added a public method to a companion object in the class that creates a new instance of this class. What is the benefit of this approach?
This is what I found:
class Foo private constructor(private val arg1: Any) {
//more code here..
companion object {
fun newFoo(arg1: Any) = Foo(arg1 = arg1)
}
}
Why is it better than this?
class Foo(private val arg1: Any) {
//more code here..
}
There are several benefits to providing a factory method instead of a public constructor, including:
It can do lots of processing before calling the construstor. (This can be important if the superclass constructor takes parameters that need to be calculated.)
It can return cached values instead of new instances where appropriate.
It can return a subclass. (This allows you to make the top class an interface, as noted in another answer.) The exact class can differ between calls, and can even be an anonymous type.
It can have a name (as noted in another answer). This is especially important if you need multiple methods taking the same parameters. (E.g. a Point object which could be constructed from rectangular or polar co-ordinates.) However, a factory method doesn't need a specific name; if you implement the invoke() method in the companion object, you can call it in exactly the same way as a constructor.
It makes it easier to change the implementation of the class without affecting its public interface.
It also has an important drawback:
It can't be used by subclass constructors.
Factory methods seem to be less used in Kotlin than Java, perhaps due to Kotlin's simpler syntax for primary constructors and properties. But they're still worth considering — especially as Kotlin companion objects can inherit.
For much deeper info, see this article, which looks at the recommendation in Effective Java and how it applies to Kotlin.
If you want to change Foo into an interface in the future the code based on the method will keep working, since you can return a concrete class which still implements Foo, unlike the constructor which no longer exists.
An example specific to android is, that Fragments should be constructed with an empty constructed, and any data you'd like to pass through to them should be put in a bundle.
We can create a static/companion function, which takes in the arguments we need for that fragment, and this method would construct the fragment using the empty constructor and pass in the data using a bundle.
There are many useful cases, for example what Kiskae described. Another good one would be to be able to "give your constructors names":
class Foo<S: Any, T: Any> private constructor(private val a: S, private val b: T) {
//more code here...
companion object {
fun <S: Any> createForPurposeX(a: S) = Foo(a = a, b = "Default value")
fun createForPurposeY() = Foo(a = 1, b = 2)
}
}
Call site:
Foo.createForPurposeX("Hey")
Foo.createForPurposeY()
Note: You should use generic types instead of Any.

Why we should avoid using open members of base class?

While i am reading document of Kotlin, i saw that we should avoid using open properties declared at base class:
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.
The document said that properties in derived class are not yet initialized when base class's constructor is called. But, how can we access derived class's properties which are not initialized, from base class constructor(I assumed that the incorrect behavior or a runtime failure were caused by this situation)? Is it possible?
I don't know kotlin, but I'm assuming that open is the same as virtual in other languages. It is unsafe to call virtual members in a base class constructor because the base constructor is called before the derived constructor. If the overridden property requires that the derived class be fully initialized it can cause errors because the derived constructor has not yet been called when you are inside the base constructor. At least that is the way it works in .NET languages like C#.
Open functions in Kotlin are functions which can be overridden by a subclass. Generally, it's a good practice to limit a class's inheritance because you should provide a class with it's necessary codes to make it overridable. If your intention is not to let a class to override your base class, then you should make it final. So Kotlin make this easy by making each class and method final by default. You can find a more detailed answer in the Objects and Class chapter of the book Kotlin in Action.
The so-called fragile base class problem occurs when modifications of a base class
can cause incorrect behavior of subclasses because the changed code of the base class no
longer matches the assumptions in its subclasses. If the class doesn’t provide exact rules
for how it should be subclassed (which methods are supposed to be overridden and how),
the clients are at risk of overriding the methods in a way the author of the base class
didn’t expect. Because it’s impossible to analyze all the subclasses, the base class is
"fragile" in the sense that any change in it may lead to unexpected changes of behavior in
subclasses.
To protect against this problem, Effective Java by Joshua Bloch (Addison-Wesley,
2008), one of the best-known books on good Java programming style, recommends that
you "design and document for inheritance or else prohibit it." This means all classes and
methods that aren’t specifically intended to be overridden in subclasses need to be
explicitly marked as final .
Kotlin follows the same philosophy. Whereas Java’s classes and methods are open by
default, Kotlin’s are final by default.
I assume you are asking about this example in Kotlin documentation:
open class Base(val name: String) {
init { println("Initializing a base class") }
open val size: Int =
name.length.also { println("Initializing size in the base class: $it") }
}
class Derived(
name: String,
val lastName: String,
) : Base(name.replaceFirstChar { it.uppercase() }.also { println("Argument for the base class: $it") }) {
init { println("Initializing a derived class") }
override val size: Int =
(super.size + lastName.length).also { println("Initializing size in the derived class: $it")
}
}
Kotlin designers followed good practices learned, from other language mistakes, so they made class, properties, and functions closed by default for overriding or inheriting. why?
let's add the open modifier to the base class property and override it:
open class Base(open val name: String) {
init { println("Initializing a base class") }
open val size: Int =
name.length.also { println("Initializing size in the base class: $it") }
}
class Derived(
override val name: String,
val lastName: String,
) : Base(name.replaceFirstChar { it.uppercase() }.also { println("Argument for the base class: $it") }) {
init { println("Initializing a derived class") }
override val size: Int =
(super.size + lastName.length).also { println("Initializing size in the derived class: $it") }
}
fun main() {
println("Constructing the derived class(\"hello\", \"world\")")
Derived("hello", "world")
}
if you run this code the output will be like below:
Constructing the derived class("hello", "world")
Argument for the base class: Hello
Initializing a base class
**Exception in thread "main" java.lang.NullPointerException
at Base.&lt;init&gt; (File.kt:6)
at Derived.&lt;init&gt; (File.kt:12)
at FileKt.main (File.kt:23)**
The error is happening because this line of code
open val size: Int =
name.length.also { println("Initializing size in the base class: $it") }
Why? when we were trying to initialize the Derived class, first the superclass is initialized first, so the initialization is done by evaluating the super constructor argument, then the properties and init blocks in their declaration order in the class.
when it comes to val size: Int = name.length.also{...} the initialization calls the name property which is overridden by the Derived class, the one that does NOT yet initialize.
so by avoiding marking the base properties by open, you protect the base class client from abusing the class.

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.