- Learn Kotlin Programming(Second Edition)
- Stephen Samuel Stefan Bocutiu
- 735字
- 2021-06-24 14:13:32
Nested classes
Working with Java, you may have come across the concept of creating a class within the body of another class, in other words, creating nested classes. You can do this in Kotlin, as follows:
class OuterClassName { class NestedClassName { } }
You could, of course, provide the access level to the nested class. If you set it to private, you will be able to create an object of NestedClassName only from within the scope of OuterClassName. To allow a code block within your module to be able to create an instance of the inner class, you will have to make use of the internal keyword. If you decide to set the access level as protected, any class that derives from OuterClassName will be able to create those instances. If the term deriving is not something you know about, don't worry; later in this chapter, we are going to address inheritance and all will be clear.
In Java, nested classes come in two flavors—static and non-static. Nested classes declared using the static keyword are called static nested classes, whereas nested classes that are declared non-static are called inner classes. A nested class is considered a member of its enclosing class as follows:
class Outer { static class StaticNested {} class Inner {} }
There is a subtle difference between static and inner nested classes. The latter have access to the enclosing class members even if they are declared private, whereas static nested classes can access static members only. Furthermore, to create an instance of the inner class, you will first need an instance of an Outer class.
Kotlin, just like Java, supports the same construct. To create the equivalent of a static nested class, you could use the following:
class BasicGraph(val name: String) { class Line(val x1: Int, val y1: Int, val x2: Int, val y2: Int) { fun draw(): Unit { println("Drawing Line from ($x1:$y1) to ($x2, $y2)") } } fun draw(): Unit { println("Drawing the graph $name") } } val line = BasicGraph.Line(1, 0, -2, 0) line.draw()
The example is pretty straightforward and shows you how it works. To allow the Line class to access a private member of the BasicGraph outer class, all you need to do is make the Line class inner; just prefix the class with the inner keyword as follows:
class BasicGraphWithInner(graphName: String) { private val name: String init { name = graphName } inner class InnerLine(val x1: Int, val y1: Int, val x2: Int, val y2: Int) { fun draw(): Unit { println("Drawing Line from ($x1:$y1) to ($x2, $y2) for graph $name ") } } fun draw(): Unit { println("Drawing the graph $name") } }
Kotlin comes with a more powerful this expression than you may be accustomed to. You can refer the outer scope to this by using the label construct this@label label construct. The following is an example:
class A { private val somefield: Int = 1 inner class B { private val somefield: Int = 1 fun foo(s: String) { println("Field <somefield> from B" + this.somefield) println("Field <somefield> from B" + this@B.somefield) println("Field <somefield> from A" + this@A.somefield) } } }
In this case, both the outer and the inner classes contain a field sharing the same name; this expression helps with disambiguation.
Working on a UI code base, you will get into a situation where, for a control (listbox, button, and so on), you will have to provide an event handler for different events as they arise. The most common example is the click event of a button on your screen. Typically, you will want to react to it and perform some action. The UI framework will expect you to provide an instance of a class; from this listener class, you will most likely want to access some state in the outer class scope. Therefore, you will end up providing an anonymous inner class, as in the following example where we count the number of clicks on a button:
class Controller { private var clicks:Int=0 fun enableHook() { button.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) {clicks++} }) } }
We assume there is a reference to a UI button and we attach the enableHook callback for its mouse events. Every time the button is clicked, it will increase the field clicks. All we have defined here, in fact, is an inner class, an anonymous one.
- scikit-learn Cookbook
- Spring Cloud Alibaba微服務(wù)架構(gòu)設(shè)計(jì)與開發(fā)實(shí)戰(zhàn)
- Java完全自學(xué)教程
- Developing Middleware in Java EE 8
- HTML5+CSS3網(wǎng)站設(shè)計(jì)基礎(chǔ)教程
- 零基礎(chǔ)入門學(xué)習(xí)Python
- 零基礎(chǔ)學(xué)單片機(jī)C語言程序設(shè)計(jì)
- Protocol-Oriented Programming with Swift
- 用戶體驗(yàn)可視化指南
- 一塊面包板玩轉(zhuǎn)Arduino編程
- Python Interviews
- Building Serverless Architectures
- R語言:邁向大數(shù)據(jù)之路(加強(qiáng)版)
- C語言程序設(shè)計(jì)教程
- Hands-On ROS for Robotics Programming