官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 津南区| 石首市| 怀来县| 读书| 新津县| 陵川县| 黄山市| 桃江县| 疏附县| 玉环县| 浦县| 西贡区| 金寨县| 古浪县| 收藏| 玉田县| 宁夏| 新野县| 体育| 互助| 寻甸| 措勤县| 临沧市| 云梦县| 绥棱县| 邢台县| 长宁县| 清苑县| 汝南县| 乌兰察布市| 太原市| 吉木乃县| 咸宁市| 淳化县| 绍兴县| 大方县| 北宁市| 内江市| 吉林省| 富源县| 龙江县|