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

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.

主站蜘蛛池模板: 湛江市| 武功县| 贵德县| 琼中| 琼结县| 普宁市| 云和县| 且末县| 饶平县| 高清| 濉溪县| 鸡东县| 察隅县| 辽阳市| 海南省| 禄劝| 漯河市| 同德县| 木兰县| 卓资县| 长汀县| 聂拉木县| 隆化县| 南漳县| 民和| 米脂县| 泰顺县| 夏邑县| 河源市| 和硕县| 丹棱县| 双柏县| 永平县| 阳新县| 进贤县| 安陆市| 汾西县| 肃北| 三穗县| 安西县| 南皮县|