Kotlin-对象表达式,对象声明及伴随对象

概述

在Java中,不管是为了实现接口,或者是抽象类,我们总是习惯使用匿名内部类。最熟悉的例子,莫过于对单击事件的监听,也就是这样写:

btn.setOnClickListener(new OnClickListener{
    // 处理单击事件逻辑
    *** 
});

尽管该匿名类只能被使用一次,这样,我们没有必要再去实现OnClickListener接口并创建一个类,从而简化了代码。可是,在Kotlin中,并没有匿名类这一概念。巧妇无米之炊啊,碰到监听事件或者回调,是不是得老老实实的写一个实现类呢???尽管Kotlin没有匿名内部类,恰巧其用object一个简单的关键字,解决了这一个问题。下面我们来看看神奇的object有什么魔法效果呢?

对象表达式

在Kotlin中,oject的神奇之对象表达式,什么是对象表达式呢?我们把它认为是一个匿名类的实例,该匿名类可以继承自某个类或者多个接口。不过,我们需要通过object关键字将其声明,表示这是一个对象。对于文章开始的单击事件监听我们可以这么写:

btn.setOnClickListener(object : OnClickListener{
    // 处理单击事件逻辑
    *** 
});


  1. 如果被继承的基类中为有参构造器且没有无参构造器时,那么必须向构造器传递适当的参数,否则编译器会报错。
  2. 对象表达式内的代码可以访问创建这个对象的代码范围内的变量,与Java不同的是,被访问的变量不需要被限制为final变量。

    val a = 10
    
    val listener = object : Info("submit"),IClickListener {
        override fun doClick() {
            println("a:$a")
        }
    
    }
    
    listener.doClick() // 打印 a:10
    
  3. “只需要对象”, 而不需要继承任何有价值的基类, 可以简单写:

    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    
    print(adHoc.x + adHoc.y)
    

对象声明

当关键字object之后指定了一个名称, 那么它就不再是“对象表达式”,而是一个对“对象声明”。此时,此对象不再是表达式,看作类的变种更为合适吧,不能再将其赋值给一个变量。在使用它时,只需要它的名字引用即可。

object MyInfo: Info("submit"),IClickListener {

    override fun doClick() {
        println("MyInfo do click, $text") // Log: MyInfo do click, , submit
    }
}

fun main(args: Array) {

    MyInfo.doClick()
}


注:

  1. 对象声明不可以是局部的(也就是说, 不可以直接嵌套在函数之内), 但可以嵌套在另一个对象声明之内, 或者嵌套在另一个非内部类(non-inner class)内。
  2. 被成名的对象可以被指定基类(类、接口)
  3. 对象声明不能指定构造函数
  4. 与对象表达式相似,如果被继承的基类中为有参构造器且没有无参构造器时,那么必须向构造器传递适当的参数,否则编译器会报错。

伴随对象

这里又有一个疑惑,实际开发时,我们总是把公用的方法,声明为静态方法,以便在任何地方都可以调用。可是,在Kotlin中,并不支持静态方法,尽管官方推荐我们使用包级别的方法,可是这远远不能满足我们的需求。有人说了,我们可以声明一个对象,在这个对象中包含这个这些公有的方法。如果这么做,每次调用时都需要创建一个新的对象,就算是使用了单例模式,也与我们的想法相离甚远。

在Kotlin中,有这么一个关键字 companion,可以用来标记对象声明。假如用其标注声明对象,又有什么效果呢?例如:在类Books内,声明对象ComBooks,并用companion关键字

class Books(var name: String, val page: Int) {
    companion object ComBooks{
        val a : Int = 10
        fun doNote() {
            println("do note")
        }
    }
}

fun main(args: Array) {
    Books.ComBooks.doNote()

    println("Book.a = ${Books.ComBooks.a}")

    println("-------------")

    Books.doNote()

}

// Log
do note
Book.a = 10
-------------
do note

从上述代码中,我们可以看出 伴随对象的调用不用创建包含伴随对象的实例,调用方式有两种,一种是类名.伴随对象.XX,另外一种方式是类名.xx。这也没有什么啊?只不过是在类的内部,声明了一个对象而已,也没有啥变化。费解….

对象表达式(声明)和伴随对象的区别

  • 对象表达式在使用的地方被立即执行。
  • 对象声明是延迟加载的, 在第一次使用的时候被初始化。
  • 伴生对象所在的类被加载,伴生对象被初始化,与Java静态成员一样。(啊啊啊 这里才算明白,伴随对象的效果啊!!!)




Kotlin讨论群:451492685
Kotlin-对象表达式,对象声明及伴随对象_第1张图片

你可能感兴趣的:(Kotlin)