I am new to kotlin. i am going through Nested class and inner class concepts in kotlin. Below is a example of nested class.
fun main(args: Array<String>) {
val demo = Outer.Nested().foo() // calling nested class method
print(demo)
}
class Outer {
class Nested {
fun foo() = "Hello world"
}
}
which gives output as
Hello world
here is the example of inner class.
fun main(args: Array<String>) {
val demo = Outer().Nested().foo() // calling inner class method
print(demo)
}
class Outer {
private val welcomeMessage: String = "Hello world"
inner class Nested {
fun foo() = welcomeMessage
}
}
which gives the outputs as
Hello world
my question is when nested class can perform the same operation as that of inner class . what is the purpose of inner class ?why we need inner class in real time?
Nested class itself is a rather straightforward idea of one concept being logically dependent on another, wider concept. You would like to declare a new nested class whenever you find yourself describing a building block of such a wider concept you do not expect to ever show up in your business logic on its own out of thin air. Therefore, an instance of such a class is accessed via the definition of the class it is nested in.
Take for an example the following structure:
class Parrot(val name: String): Animal {
//vals and vars useful for a parrot
class HealthyConditions {
val featherColour: String // Does not really apply to Dogs, Cats, Fish, etc.
val cageSize: Size // Does not really apply to Dogs, Cats, Fish, etc.
val weightInGrammes: Int
val dailySleepInHours: Int
fun isUnderweight(currentWeightInGrammes: Int): Boolean {
return currentWeightInGrammes < weightInGrammes
}
}
}
Now, the concept of healthy living conditions is common and important for any Animal
this system may describe, but from one species to another there are multiple completely different factors to take into consideration. Trying to prepare a single common HealthyConditions<Animal>
class for all of them at once will likely lead to unreadable and hard to maintain code, full of if
s and else
s. Therefore, it may make more sense for the developer to define concise, tidy nested classes for each Animal
on its own. Later on, these will be accessed through Parrot.HealthyConditions()
, Cat.HealthyConditions()
, etc. instead of HealthyConditions.getForSpecies(animal)
.
Inner class is a Kotlin concept built on top of the idea of a nested class. While some details are very specific for a given concept and therefore are being described as nested classes, what if those details vary even further depending on the wider concept's instance? Then accessing it using the class definition may not be all it takes to operate properly. Inner classes are therefore accessed through the call to an instance of the class they are an inner class of.
Let's get back to our Parrot
shall we?
class Parrot(val name: String, var age: Int): Animal {
//vals and vars useful for a parrot
inner class HealthyConditions {
val featherColour: String // Does not really apply to Dogs, Cats, Fish, etc.
val cageSize: Size // Does not really apply to Dogs, Cats, Fish, etc.
val weightInGrammesByAge: Map<Int, Int>
val dailySleepInHoursByAge: Int<Int, Int>
/** variable 'age' from the Parrot class can be accessed only because the HealthyConditions class is marked inner! */
fun isUnderweight(currentWeightInGrammes: Int): Boolean {
return weightInGrammesByAge[age] > currentWeightInGrammes
}
}
}
How much a healthy Parrot
should weigh changes over the course of the said parrot's life. A hatchling weighing a couple hundreds of grams is fine but a grown individual under 2 kilograms might need some attention. Therefore, the question of whether or not a Parrot
is underweight at X grams cannot be answered easily, but should we ask if Bob the Parrot should gain some weight, we could use what we know about Bob to determine the answer. In order to do that, the HealthyConditions
class will be accessed through Parrot("Bob", 5).HealthyConditions()
.
Now, to top it off, you might still wonder if accessing parent class properties is really useful for the inner class. After all, you could simply provide the age
value wherever you call the isUnderweight()
function, right? That is true, of course, but when discussing nested classes we decided each Animal
deserves their own HealthyConditions
implementation. For a Dog
class, the breed of the dog is just as important in determining its correct weight as is its age. For yet other species, the gender will also be of importance. Meaning that, without direct access of the inner class to its parent's properties, Healthcheck
interface's function checkIfUnderweight()
would have to accept awfully lots of different, probably nullable, variables in order to be applicable to all different kinds of animals in the system.
I took a lot of time talking over the concept without many code samples but from what I understood you do not struggle with the implementation, but with the justification for even implementing the code in the first place. Also, forgive me if the "Animal classes" example I came up with may appear dumbed down - the truth is it was the first I came up with. ;)
Anyways, I hope this short read may help you understand the concept and its use cases better. Safe coding and may the bugs stay away from you!
The official Kotlin documentation is quite self-explanatory:
A nested class marked as inner can access the members of its outer class. Inner classes carry a reference to an object of an outer class:
Perhaps you do not understand what this means.
Concretely, in your code sample, you can only access welcomeMessage
which is defined in Outer
from code in Nested
when Nested
is marked as inner
. Try removing inner
, and your code won't compile.
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