Kotlin基础八:object

114 阅读3分钟

前言

Kotlin基础object关键字。创建一个类做了轻微改动的类的对象,不用显式声明的子类。Kotlin用对象表达式和对象声明处理这种情况。

对象表达式

Java中匿名对象创建用new,Kotlin中创建一个匿名对象使用关键字object

// java中
view.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v){}
});
// kotlin中用object声明匿名类
view.setOnClickListener(object:View.OnClickListener{
    override fun onClick(v:View?){}
})

父类使用open才能被继承

open class  Person(name:String){}
open class Student(private val name:String):Person(name){}
val student = object :Student("xiake"){}

当仅仅需要一个对象,不需要特殊超类型

fun test() {
    println("x:${point.x} y:${point.y}")
}
private val point = object {
    val x =100
    val y =100
}

匿名对象可用作本地和私有作用域中声明的类型。匿名对象作为共有函数的返回类型或共有属性类型,该函数或属性实际类型是匿名对象声明的超, 没有声明任何类型就是Any。在匿名对象中推荐加的成员将无法访问。

fun test() {
    val x = point.x // 报错,无法访问x
}
// 共有属性point返回时一个Any类型
val point = object {
    val x =100
    val y =100
}

对象表达式中代码可以访问来自包含它的外部作用域的变量

class View{
    private val name = "view"
    private val point =object{
        val x =100
        val y = 100
        val pName = name
    }
}

对象声明

object关键字上根一个名称。

object A{
    const val TAG = "a"
    fun getB(){
        println("b")
    }
}

对象声明不是表达式,不能用赋值句的右边。开发中常用object声明的对象式单例。点击Decompile反编译Java代码。使用object声明的对象反编译成Java也只是class类定义了私有的无参构造函数,该类的static中创建一个A对象,并给了变量INSTANCE。

A.INSTANCE.getB()

这些对象可以有自己的超类型

interface Info{
    fun getInfo()
}
object A:Info{
    override fun getInfo() {
        
    }
}

对象声明不能在局部作用域(直接嵌套在函数内部),可以嵌套到其他对象声明或非内部类中

object A{
    const val TAG="=A="
    object B{
        const val TAG="=B="
    }
}

在声明的对象中嵌套声明B对象

class A{
    object B{
        const val TAG="=B="
    }
}

类A中嵌套声明B对象

伴生对象

companion关键字标记内部的对象声明

fun test() {
    val tag = Person.TAG
    // 外部类名访问伴生对象或方法
    val instance = Person.newInstance()
}
class Person private constructor(){
    companion object Factory{
        const val TAG="factory"
        fun newInstance() = Person()
    }
}

通常省略伴生对象名称

fun test() {
    val tag = Person.TAG
    val instance = Person.newInstance()
}
class Person private constructor(){
    companion object{
        const val TAG="factory"
        fun newInstance() = Person()
    }
}

伴生对象默认名Companion

fun test() {
    val tag = Person.Companion.TAG
    val instance = Person.Companion.newInstance()
}

反编译成java,类内部定义了一个静态内部类Companion,该伴生兑现的默认类名。 用类Person内部声明的伴生对象实现了接口Factory

interface Factory<T>{
    fun create():T
}
class Person{
    companion object:Factory<Person>{
        override fun create(): Person=Person()
    }
}

对象表达式和对象声明差异

  • 对象表达式在使用它们的地方立即初始化
  • 对象声明式第一次被访问到时延迟初始化
  • 伴生对象初始化在相应类被加载时,与Java静态初始化器的语义相匹配

总结

在Kotlin相关开发中object随处可见,要理解其中的含义,所有的开发语言都是相通的,大致原理之间有相互的联系。