I'm trying to pass value to constructor and print the values.
open class Car(c: Int){
open var cost: Int = c
init {
println("This comes First $cost")
}
}
open class Vehicle(cc: Int) : Car(cc) {
override var cost: Int = 20000
init {
println("This comes Second $cost")
}
fun show(){
println("cost = $cost")
}
}
fun main() {
var vehicle = Vehicle(1000)
vehicle.show()
}
Output
This comes First 0
This comes Second 20000
cost = 20000
if i just comment this line
override var cost: Int = 20000
output would be
This comes First 1000
This comes Second 1000
cost = 1000
In Java to create a mutable property cost
, you need to define a field cost and a getter and setter:
public class Car {
private int cost;
public Car(int c) {
this.cost = c;
System.out.println("This comes First " + getCost());
}
public int getCost() { return cost; }
public void setCost(int cost) { this.cost = cost; }
}
Kotlin has the concept of a property embedded in the language, so you can achieve the same with only creating a var property as you did:
open class Car(c : Int){
open var cost : Int = c
init {
println("This comes First $cost")
}
}
This is much more concise from the developer perspective, but the implementation is the same. Kotlin compiler is generating a field cost, a get method and set method for us under the hood. Now the interesting part. When you make the cost property in the parent class open and overrides it in the child class, you are actually overriding the get method. It is not possible to override a field, neither in Kotlin nor Java.
As @Pawel mentioned in his answer that's the java code for the Vehicle child class:
public class Vehicle extends Car {
private int cost = 20000;
@Override
public int getCost() {
return this.cost;
}
@Override
public void setCost(int var1) {
this.cost = var1;
}
public final void show() {
System.out.println("cost = " + getCost());
}
public Vehicle(int cc) {
super(cc);
System.out.println("This comes Second " + getCost());
}
}
When you execute println("This comes First $cost")
in the parent class, you are actually executing System.out.println("This comes First " + getCost());
and the actual getCost()
being called is the one in the child class Vehicle. As the child class cost field has not been initialized yet, as we are still executing the super(cc)
call, its value is zero.
Have you looked at generated bytecode and tried to reverse decompile it back to java? If you're confused how Kotlin works under the hood often times it can help you understand.
In this case your classes in Java would look like this (i decompiled your code and cleaned it up a little):
public class Car {
private int cost;
public int getCost() {
return this.cost;
}
public void setCost(int var1) {
this.cost = var1;
}
public Car(int c) {
this.cost = c;
System.out.println("This comes First " + getCost());
}
}
public class Vehicle extends Car {
private int cost = 20000;
public int getCost() {
return this.cost;
}
public void setCost(int var1) {
this.cost = var1;
}
public final void show() {
System.out.println("cost = " + getCost());
}
public Vehicle(int cc) {
super(cc);
System.out.println("This comes Second " + getCost());
}
}
What's happening is open var
is just declaration for setter and getter which Vehicle
overrides.
Remember that initialization of super class always happen before child, so when Car
constructor is executed Vehicle
is still not initialized (Vehicle.cost
is still 0).
That means in first case:
This comes First 0 // Car constructor prints 0 because it returns Vehicle.cost which is unitialized
This comes Second 20000 // Vehicle constructor returns initialized value
cost = 20000
And in second case where you DON'T override the cost, both Car
and Vehicle
return Car.cost
:
This comes First 1000 // Car constructor assigns constructor parameter to Car.cost and returns it
This comes Second 1000 // Vehicle constructor returns Car.cost as well
cost = 1000
Also note that in first case your constructor parameter is meaningless: it gets assigned to Car.cost
but that field is inaccessible because it's shadowed by Vehicle.cost
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With