Kotlin入门-带着问题,理解 对象表达式和对象声明

在这里插入图片描述

前言

本文我们需要了解几个点。
①object与any的区别?
②private跟非private返回值的区别?
③Kotlin中单例模式怎么实现?又如何调用?
④伴生对象什么时候产生?可以如何调用?
⑤对象表达式、声明对象、伴生对象 初始化的时机?

本节目录不重要。带着这些问题就可以了。


作用

Kotlin的对象表达式,再一次简化了,对某个类做轻微改动时,且不需要去声明一个新的子类。


对象表达式

通过匿名内部类

与java一样,或继承、或实现、或通过构造函数传值给其参数。

匿名对象只在本地和私有作用域中声明

范例一
window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) { /*……*/ }

    override fun mouseEntered(e: MouseEvent) { /*……*/ }
})

知识点复习

理解一下Kotlin中,object与any的区别

  • any
    定义的方法有:toString()、equals()、hashCode() 3个
  • Object类
    定义的方法有:toString()、equals()、hashCode()、getClass()、clone()、finalize()、notify()、notifyAll()、wait()、wait(long)、wait(long,int) 11个

我们看一段英文解析,或许更加清晰。

Kotlin compiler treats kotlin.Any and java.lang.Object as two different types,
but at runtime they are represented with the same java.lang.Object class.

编译器认为Any和Object是不同的类型;但是在运行时,Any和Object表现出来是一样的。

这也是Kotlin可以和Java互通的一个提现。运行时,我们都一样的。

解析

  • object:MouseAdapter即是new MouseAdapter()
  • 如果不需要 super继承,仅需要一个object怎么写呢
	    private fun foo() = object {
            val x: String = "x"
        }

把冒号 后面的去掉

范例二
class C {
    // 私有函数,所以其返回类型是匿名对象类型
    private fun foo() = object {
        val x: String = "x"
    }

    // 公有函数,所以其返回类型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // 没问题
        val x2 = publicFoo().x  // 错误:未能解析的引用“x”
    }
}

注意
留意上述范例中的 注释部分

  • private函数,会返回 匿名对象类型
  • 非private函数,返回的是Any类型

对象声明

Kotlin 使用 object 关键字来声明一个对象

通过对象声明,可以获得一个单例单例单例单例 重要的事情说三遍

范例
object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ……
    }

    val allDataProviders: Collection<DataProvider>
        get() = // ……
}

这就是对象声明。
仿佛是你声明了一个变量一样

如何调用呢?

DataProviderManager.registerDataProvider(……)

单例的调用不用getInstance了。砍砍砍,砍代码量啊

来看范例一
var data1 = DataProviderManager
var data2 = DataProviderManager
data1.name = "test"
print("data1 name = ${data2.name}")

//这里data1.name 和data2.name是一样的

注意
object声明的单例,只能通过类名来访问!!!
Kotlin的单例,避免了getInstance,直接调用。
砍砍砍,砍代码量啊

看个范例二
class Engineer {
    var name = "wangxueming"
    object Info {
        var sex = "man"
        fun showName(){
            print{"desk legs $name"} // 错误,不能访问到外部类的方法和变量
        }
    }
}
fun main(args: Array<String>) {
    var wxm = Engineer()
    wxm.Info.sex // 错误,不能通过外部类的实例访问到该对象
    Engineer.Info.sex // 正确
}

通过object声明的对象,是单例,而且!只能!通过 类名 范文。不得不说,这避免了不少麻烦事。
明摆的事情!我访问单例,肯定就是那么个实例。


伴生对象

用 companion 关键字标记
与外部类关联在一起!!!如影随形
可以直接通过外部类访问到对象的内部元素

范例
class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}
val instance = MyClass.create()   // 访问到对象的内部元素

也可以这样

class MyClass {
    companion object {
    }
}

val x = MyClass.Companion

注意

  • 伴生对象并不是静态成员, 是 实例成员
  • 一个class里面只能声明一个内部关联对象
  • 即关键字 companion 只能使用一次

对象表达式和对象声明之间的语义差异

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

小结

总体来说,在Kotlin中,通过object实现了单例,并简化了单例模式下实例的调用方式;
通过伴生对象,解决了部分的 初始化需求,但是,又在一些情况下,弱化伴生对象的存在(companion object修饰的类名可以不写)。

将减少代码量,作为最高意志。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章