- 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.
- Python編程自學手冊
- ThinkPHP 5實戰
- 造個小程序:與微信一起干件正經事兒
- 樂高機器人設計技巧:EV3結構設計與編程指導
- SEO實戰密碼
- Getting Started with Python Data Analysis
- JavaCAPS基礎、應用與案例
- Test-Driven Machine Learning
- HTML+CSS+JavaScript網頁設計從入門到精通 (清華社"視頻大講堂"大系·網絡開發視頻大講堂)
- Django 3.0應用開發詳解
- Unity 2017 Game AI Programming(Third Edition)
- SignalR:Real-time Application Development(Second Edition)
- Using Yocto Project with BeagleBone Black
- Java RESTful Web Service實戰
- Python程序設計