美文网首页
About Kotlin-Kotlin中的类2

About Kotlin-Kotlin中的类2

作者: deep_sadness | 来源:发表于2017-08-18 17:23 被阅读19次

    About Kotlin(2)

    继续昨天的部分。介绍Kotlin中的类。

    Kotlin中的类

    抽象类和接口

    抽象类

    跟Java一样,使用abstract关键字

    open class Base{
      open fun f(){}
    }
    abstract class Derived:Base(){
      override abstract fun f()
    }
    
    接口
    //内部可以直接写实现
    interface MyInterface{
      fun bar()
      fun foo(){    //默认实现
        println("foo")
      }
    }
    
    //接口中可以写属性。不允许初始化。实现类必须初始化
    interface MyInterface2{
      var name:String //抽象
    }
    class MyImpl:MyInterface2{
      override var name:String="override name" //重载属性
    }
    

    密封类

    使用sealed修饰符修饰。其实是一组类的集合。可以用来表示受限的类的继承结构。
    其也可以有子类,所有子类也必须在相同的文件中声明。
    密封类从某种意义上说,它们是枚举类的扩展:枚举类型的值集也受到限制,但每个枚举常量仅作为单个实例存在,而密封类的子类可以包含多个实例并包含状态。这样又具备了枚举不具备的灵活性。

    sealed class BaseClass {
    
        class Test1 : BaseClass() {
            override fun test() {
                println("Test1实例")
            }
    
        }
        class Test2 : BaseClass() {
            override fun test() {
                println("Test2实例")
            }
        }
        object Test3 : BaseClass() {
            override fun test() {
                println("Test3实例")
            }
        }
        open fun test() {
            println("BaseClass实例")
        }
    }
    
    fun test(instance: BaseClass)=when(instance){
        is BaseClass.Test1-> instance.test()
        is BaseClass.Test2-> instance.test()
        is BaseClass.Test3->instance.test()
    }
    
    fun main(str: Array<String>) {
        test( BaseClass.Test1() )
        test( BaseClass.Test2() )
        test( BaseClass.Test3 )
    }
    

    内部类

    inner标记

    使用inner标记才能够访问外部类的变量

    class Outer{
      private val bar:Int = 1
      inner class Inner{
        fun foo()=bar
      }
    }
    //调用的方式.和java类的内部类调用的方式相同
    val demo = Outer().Inner().foo()
    

    嵌套类

    不用inner标记,直接写在类的内部的类,在kotlin中称为所谓的嵌套类

    class Outer{
       private val bar: Int = 1
       class Nested{
         fun foo()=2
       }
    }
    //嵌套类的调用有点像静态内部类。
    val demo = Outer.Nested().foo()
    

    枚举类

    枚举类最基本的用法是实现类型安全的枚举

    enum class Direction{
      NORTH,SOUTH,WEST,EAST
    }
    //和Java一样,每个枚举类都是枚举的实例,可以被初始化
    enum class Color(val rgb:Int){
      RED(0xFF0000),
      GREEN(0x00FF00),
      BLUE(0x0000FF)
    }
    

    匿名类

    enum class ProtocolState{
      WAITING{
        override fun signal()=WAITING
      },
      TALKING{
        override fun signal()=TALKING
      };//这里需要用分号分割
      abstract fun signal():ProtocolState
    }
    

    Object类(及匿名类)

    在Kotlin中使用对象表达式对象声明进行表示

    对象表达式(匿名类)

    匿名类其实就是在Java中的匿名内部类。
    java中调用方法时,提供的匿名内部类

    fun countClicks(window:JComponent){
      var clickCount = 0
      val enterCount=0
      
      //通常的情况,使用Object开头就可以
    window.addMouseListener(object:MouseAdapter()){
      override fun mouseClicked(e:MouseEvent){
        //与Java不同的是,甚至可以直接访问变量。(未被final修饰)!
        clickCount++
        enterCount++
      }
      ...
    }
    }
    
    //多个超类的情况
    open class A(x:Int){
      public open val y:Int=x
    }
    interface B{...}
    val ab :A=object:A(1),B{
      override val y = 15
    }
    
    //如果只是需要一个对象,什么都不需要的话。也可以直接写
    fun foo(){
      val adHoc = object{
        var x:Int = 0
        var y:Int =0
      }
      println(adHoc.x+adHoc.y)
    }
    

    这里有一点值得特别注意的的是:
    匿名对象可以用作只在本地私有作用域中声明的类型。只能做为私有函数的返回值。

    class C{
      //私有函数,所以其返回雷士的对象是匿名对象
        private fun foo()=object{
            val x :String="x"
        }
      //默认都是public final的方法.使用对象声明返回的类型是Any
        fun publicFoo()=object{
            val x:String="x"
        }
      
        fun bar(){
            val x1= foo().x //可以直接访问
            val x2= publicFoo().x //错误!未能解析的引用"x"
        }
    }
    

    对象声明

    单例

    是指使用object关键字声明的一种类。这种类是单例,并且所有的成员都是静态方法。

    object DataProviderManager{
      fun registerDataProvider(provider:DataProvider){}
    }
    
    伴生对象

    类内部的对象声明可以使用companion关键字标记

    class MyClass{
    //就是静态内部类咯?但是每个类的伴生对象只能有一个!?
      companion object Factory{
        fun create():MyClass=MyClass()
      }
    }
    
    //调用方式类似于Java中的静态方法
    val instance = MyClass.create()
    
    //如果按照下列写法,调用时,可以使用名称 Companion
    class MyClass{
      companion object{}
    }
    
    val x = MyClass.Companion
    

    这里需要注意的是:

    在 JVM 平台,只有使用 @JvmStatic 注解,才能将伴生对象的成员生成为真正的静态方法和字段。否则,都只是实例变量

    //即使伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员,而且,例如还可以实现接口:
    interface Factory<T> {
        fun create(): T
    }
    class MyClass {
        companion object : Factory<MyClass> {
          //注意需要写Override
            override fun create(): MyClass = MyClass()
        }
    }
    //当然,在 JVM 平台,如果使用 @JvmStatic 注解,你可以将伴生对象的成员生成为真正的静态方法和字段。
    //@JvmStatic 注解也可以应用于对象或伴生对象的属性, 使其 getter 和 setter 方法在该对象或包含该伴生对象的类中是静态成员。更多详细的内容之后再看
    class MyClassJVM {
         companion object : Factory<MyClassJVM> {
           @JvmStatic override fun create(): MyClassJVM = MyClassJVM()
        }
    }
    

    到这里,就大概把Kotin中的类汇总完了。接下来,也还是会按照参考文章的这个思路。记录Kotlin中的属性。方法。修饰符。

    相关文章

      网友评论

          本文标题:About Kotlin-Kotlin中的类2

          本文链接:https://www.haomeiwen.com/subject/coiarxtx.html