1. Overview
In this article, we will discuss the Kotlin nested and inner classes. Sometimes we need to group classes and interfaces in one place to create more readable and maintainable code. It increases the use of encapsulation by enabling us to hide the data in a single entity to protect it from outside access.
2. Nested class Kotlin
We can nest classes in other classes.
For example, the class Student
has a nested class Subject
. We also have a subjectFunc
function in the Subject
class. The below code will work fine as Kotlin allows you to declare a class inside another class.
class Student { private val studentId: Int = 1 class Subject { fun subjectFunc() = "Nested function" } } fun main() { println(Student.Subject().subjectFunc()) }
Suppose you want to access and instantiate your nested class from outside class or the main
function. How to do it? You can access your nested class only through your outer class.
The syntax for instantiating the nested class is:
OuterClassName.NestedClassName()
Note the outer class name with a dot at the starting before your nested class instantiation. In the above example, Student.Subject()
creates an instance of the Subject
class, and then you can access its members using the instance.
2.1. Nestes Interfaces
You can also nest your interfaces in other classes and interfaces. Let’s take an example.
In the below code, the Outer
class contains an interface OnClickInterface
that also holds another interface OnProcessInterface
.
class Outer { private val outerVariable: Int = 1 interface OnClickInterface { fun click() interface OnProcessInterface { fun process() } } class Nested : OnClickInterface { override fun click() { println("Click") } } }
You can nest interfaces in classes, classes in interfaces, and interfaces in interfaces.
interface OuterInterface { class NestedClass interface NestedInterface } class OuterClass { class NestedClass interface NestedInterface }
3. Inner class Kotlin
You can mark the nested class as the Inner class using the keyword Inner
. The syntax to access the inner class is:
OuterClass().InnerClass()
3.1. Kotlin inner class access outer variable
Sometimes we will need to access the outer class members from the nested class. But Nested class can’t access the outer class members.
For example, the below Nested
class can’t access your Outer
class variable foo
.
class Outer { val foo: Int = 1 class Nested { fun print() { println(foo) } } } fun main() { Outer.Nested().print() }
You can access the outer class members if you declare your nested class as Inner class. To put it in another way, a nested class marked as inner
can access the members of its outer class by holding a reference to the outer class object.
The below code throws the error “Constructor of inner class Nested can be called only with receiver of containing class” as you call the Nested class without the outer class instance.
class Outer { val foo: Int = 1 inner class Nested { fun print() { println(foo) } } } fun main() { Outer.Nested().print() }
Makes little sense? No worries. Let’s see the below code that will work. We access the nested class using the instance of the outer class. Therefore, the nested class can access all the outer class members.
class Outer { val foo: Int = 1 inner class Nested { fun print() { println(foo) } } } fun main() { Outer().Nested().print() }
3.2. Qualified this
Suppose you have the same variable name in both outer and inner classes. The inner class variable takes precedence over the outer class variable inside the inner class.
For example, both the Student
and Subject
classes have the same variable name
. The print
function in the Subject
class displays the subject name.
class Student { val name: String = "John" inner class Subject { val name: String = "Maths" fun print() { println(name) } } } fun main() { Student().Subject().print() }
What if you want to print Student
‘s name
instead of Subject
‘s name. You can do it using the qualified this. The This
with qualifier label enables us to point to the scope we want. In the this@label
, where @label
is a label on the scope this
is meant to be from. The implicit label for the scope would be the class or function name.
For example, the Student
class has an implicit label @Student
(its class name), so this@Student
refers to the outer class scope. The same way Subject
class has an implicit label @Subject
therefore this@Subject
refers to the inner class Subject
scope.
this@Student.name
will refer to the Student
class member name
. If this
has no qualifiers, it refers to the innermost enclosing scope. Therefore,
refers to the this.name
Subject
class which is the innermost enclosing scope.
class A { val foo: Int = 1 inner class B { val foo:Int = 2 fun print() { println(this@A.foo) println(this@B.foo) println(foo) } } } fun main() { A().B().print() }
4. Conclusion
In this article, we have learned about the Kotlin Nested and Inner classes.
See our Kotlin articles to know other topics.