Kotlin学习笔记之 8

作者: super_shanks | 来源:发表于2019-03-26 11:36 被阅读7次

8.Kotlin 扩展

  • 扩展函数

    我们可以在任何时刻,任何地方,去帮类添加扩展函数,形式就是如下

    fun 扩展类.扩展方法(){
          println("123456")
    }
    

    然后能在任何地方任何时刻都能使用这个扩展的方法。

    如果扩展函数和成员函数同名,那么优先使用成员函数。

    可以扩展一个空的对象,空的对象我们使用Any?去表示

    fun Any?.newString(): String {
          if (this == null) return "null"
          // 空检测之后,“this”会自动转换为非空类型,所以下面的 toString()
          // 解析为 Any 类的成员函数
          return toString()
      }
    

    这样一来我们在任何时刻去调用toString()方法的话都不会出现空指针的异常

  • 扩展属性

    我们还能针对属性做扩展,比如我们想要为List类加一个属性lastIndex,代表列中的最后一个值的索引。

    val <T> List<T>.lastIndex : Int
          get() = size - 1 
    

    扩展属性只能用val来形容,即扩展的属性只能读取,不能修改。

  • 伴生对象的扩展

    伴生对象是我们在kotlin中一般用来处理单例的方式,可以简要的在此做一下说明,我们主要使用companion关键字来处理

    //kt文件
    class TestInstance{
          companion object 
      }
      
    //decompile java
    public final class TestInstance {
         public static final TestInstance.Companion Companion = new TestInstance.Companion((DefaultConstructorMarker)null);
      
         public static final class Companion {
            private Companion() {
            }
      
            public Companion(DefaultConstructorMarker $constructor_marker) {
               this();
            }
         }
      }
    

    就是比较经典的单例模式,在kotlin中我们可以直接通过TestInstance.Companion的方式去访问这个类的单例,我们可以理解成就是TestInstance.getInstance()方法

    半生对象的扩展如下:

    fun TestInstance.Companion.newFun(a : String) : Int{
          val b = a + "1"
          return b.length
      }
      
      val TestInstance.Companion.property : Int
         get() = 1
    
  • 扩展的作用域

    作用域较广,跨包名调用也可以直接通过import的方式直接使用。

  • 扩展中遇到的各种冲突或同名问题

    • 情况1 同名扩展函数

      如果出现了同名扩展函数,则调用内部函数,不调用扩展函数

      fun D.toString(){
             Log.e("extension", "toString")
         }
      

      并没有用,最终会调用类D自己的toString方法

    • 情况2 扩展函数中调用内部同名函数

      扩展函数中出现了扩展类中和本类中都有的函数,以扩展类中的为主,若想使用本类中的函数,需要加上标注this@ClassName

      class D {
             fun hello(){}
         }
         
      class C {
             fun hello(){}
             
             fun D.newFun(){
                 hello()
                 this@C.hello()
             }
      }       
      

      第一个hello方法用的是D中的hello,如果想使用C中的hello的话需要加上this@C

    • 情况3 继承中出现的扩展

      首先,我们应该很容易理解,如下这种情况,即参数类型是D,所以用的应该是D的扩展函数foo()

      open class D {
         }
         
         class D1 : D() {
         
         }
         
         open class C {
         
             open fun D.foo() {
                 println("D.foo in C")
             }
         
             open fun D1.foo() {
                 println("D1.foo in C")
             }
         
             fun caller(d: D) {
                 d.foo() // 调用扩展函数
             }
        }
      

      如果C1继承了C,同时复写了扩展函数,如下:

      class C1 : C() {
             override fun D.foo() {
                 println("D.foo in C1")
             }
         
             override fun D1.foo() {
                 println("D1.foo in C1")
             }
         }
      

      那么调用C1caller方法,无论传D类型还是D1类型,最终打印的都是println("D.foo in C1")

相关文章

网友评论

    本文标题:Kotlin学习笔记之 8

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