Extension functions are really-really helpful while writing code in Kotlin. You don’t have to extend the class but you can add the functionality to even a final (non-open) class which will be resolved statically but how about extension properties.
A very interesting question asked to me during an interview or even a general situation where we need to add a property (variable) to an existing class without extending it.
Is it even possible?
Can we add a property/variable as an extension to an existing class?
According to the theory of extension functions, this is not possible since you can only add the extension functions but not properties, but there is a workaround which can solve the purpose.
Let’s try to understand that workaround first and then talk about the limitations.
Say there is a class name Temperature
which only has one property tempInCelsius
which it takes as a parameter in the constructor.
class Temperature(var tempInCelsius: Float)
Now I want to add one more property tempInFahrenheit
which will be holding the same value of temperature but in Fahrenheit.
I actually can’t add a property for the same but I can add getter and setter which are nothing but the extension functions to the same.
var Temperature.tempInFahrenheit: Float
get() = (tempInCelsius * 9 / 5) + 32
set(value) {
tempInCelsius = (value - 32) * 5 / 9
}
and I can call this property simply like any other property of that class.
val temp = Temperature(32f)
println(temp.tempInFahrenheit)
temp.tempInFahrenheit = 90f
println(temp.tempInCelsius)
What exactly we did?
We didn’t add any property but using the syntactical sugar, we added one setter and one getter under the name of one variable, which ultimately read and writes to one of the existing variables.
This setter function takes a float value and the setter also return the float value. This might look like a new property but this is not. This is just a set of new getter setter.
What are the limitations?
Since we never added an actual property, we can’t use the backing field.
var Temperature.tempInFahrenheit: Float = 32 <e>//compilation error</e>
<e>initializers are not allowed for extension properties</e>
var Temperature.tempInFahrenheit: Float
get() = field <e>//compilation error</e>
set(value) {
field = value <e>//compilation error</e>
}
Also, we can only do some processing but to store that value we need some existing variable only within the class. We can never save the value in the so-called extension property variable (tempInFahrenheit
in our case) as at the end it is not a property.
So to answer the question, there is no possible way you can add an extension property with backing field or which can store value but using syntactical sugar, you can add a property which ultimately is a getter or/and setter which can do the job for you.
Read more about extension functions on the below links.