Kotlin中的类和对象的工作方式与大多数面向对象语言中的相同:通常,定义一个类,然后创建该类的多个实例:

import java.util.Random

class LuckDispatcher { //1 

    fun getNumber() { //2 

        var objRandom = Random()

        println(objRandom.nextInt(90))

    }
}

fun main() {

    val d1 = LuckDispatcher() //3

    val d2 = LuckDispatcher()

    d1.getNumber() //4 

    d2.getNumber()

}

在Kotlin中,可以使用 object 关键字获取具有单一实现的数据类型。

单一 : 的含义类似于Java中单例模式,它确保即使多个线程尝试创建该类,也只创建该类的一个实例。

要在Kotlin中实现这一点,您只需要声明一个object :没类,没有构造函数,只有一个惰性实例。类似懒汉式单例,它将在访问对象时创建一次。

object 表达式

以下是对象表达式的基本典型用法:

  • 要创建一个继承自某个(或某些)类型的匿名类的对象 通常使用以下方式

例如给Viewpager 添加PagerChangeListener

viewPager.addOnPageChangeListener(object :ViewPager.OnPageChangeListener{
    override fun onPageScrollStateChanged(state: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
    override fun onPageSelected(position: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
})
  • 如果超类有一个构造函数,则必须传递适当的构造函数参数给它。 多个超类型可以由跟在冒号后面的逗号分隔的列表指定:
open class A(x: Int) {

    public open val y: Int = x

}

interface B { …… }

val ab: A = object : A(1), B {

    override val y = 15

}
  • 对于一个简单的对象或属性结构。使用object 表达式后访问一个成员不需要再(创建一个对象,声明其成员并在一个函数中访问它)
fun rentPrice(standardDays: Int, festivityDays: Int, specialDays: Int): Unit { //1

    val dayRates = object { //2

        var standard: Int = 30 * standardDays

        var festivity: Int = 50 * festivityDays

        var special: Int = 100 * specialDays

    }

    val total = dayRates.standard + dayRates.festivity + dayRates.special //3

    print("Total price: $$total") //4

}

fun main() {

    rentPrice(10, 2, 1) //5

}

object 声明

它不是表达式,不能用于变量赋值。使用它来可以直接访问其成员函数 :

object DoAuth { //1   创建一个 objeDoAuth (object 声明)

    fun takeParams(username: String, password: String){ //2   定义object 方法

        println("input Auth parameters = $username:$password")

    }
}

fun main(){

    DoAuth.takeParams("foo", "qwerty") //3  直接使用声明调用其方法。 object  是在其这个时候创建的

}

Companion Objects

类中的对象声明定义了另一个有用的情况:伴生对象。从语法上讲,它类似于Java中的静态方法:使用类名作为限定符来调用对象成员。

class BigBen { //1                              创建一个类

    companion object  Bonger {     //2     定义一个名字为 Bonger (可以省略)伴生对象

        fun getBongs(nTimes: Int) { //3  定义伴生对象方法

            for (i in 1 .. nTimes) {

                print("BONG ")
            }
        }
    }
}

fun main() {

    BigBen.getBongs(12)          //4   使用类明直接调用伴生对象方法

}

即使伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员,而且,例如还可以实现接口:

interface Factory<T> {

    fun create(): T

}

class MyClass {

    companion object : Factory<MyClass> {

        override fun create(): MyClass = MyClass()

    }
}

val f: Factory<MyClass> = MyClass

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

对象表达式和对象声明之间有一个重要的语义差别:

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