- 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.
- 企業級Java EE架構設計精深實踐
- Magento 2 Theme Design(Second Edition)
- Blockly創意趣味編程
- Python應用輕松入門
- 教孩子學編程:C++入門圖解
- Nginx Essentials
- 響應式架構:消息模式Actor實現與Scala、Akka應用集成
- Unity Character Animation with Mecanim
- Arduino可穿戴設備開發
- SEO教程:搜索引擎優化入門與進階(第3版)
- 從零開始學算法:基于Python
- LabVIEW入門與實戰開發100例(第4版)
- Azure for Architects
- 軟件自動化測試實戰解析:基于Python3編程語言
- C++教程