Kotlin:类中对象和伴随对象之间的区别

时间:2017-05-05 22:29:29

标签: object kotlin companion-object

kotlin中一个对象和一个伴侣对象有什么区别?

示例:

class MyClass {

    object Holder {
        //something
    }

    companion object {
        //something
    }
}

我已经读过,如果包含的参数/方法与其类密切相关,则应使用伴随对象。

但为什么还有可能在课堂上声明一个普通的对象呢?因为它的行为与伴侣完全相同,但它必须具有名称。

它的“静态”(我来自java方面)生命周期可能有区别吗?

6 个答案:

答案 0 :(得分:37)

有两种不同类型的object用途,表达式声明

对象表达

当一个类需要稍微修改时,可以使用一个对象表达式,但是没有必要为它创建一个全新的子类。匿名内部类就是一个很好的例子。

    button.setOnClickListener(object: View.OnClickListener() {
        override fun onClick(view: View) {
            // click event
        }
    })

需要注意的一点是,匿名内部类可以从封闭范围访问变量,而这些变量不必是final。这意味着在匿名内部类中使用的不被视为final的变量在访问之前可能会意外地更改值。

对象声明

对象声明类似于变量声明,因此不能在赋值语句的右侧使用。对象声明对于实现Singleton模式非常有用。

    object MySingletonObject {
        fun getInstance(): MySingletonObject {
            // return single instance of object
        }
    }

然后可以像这样调用getInstance方法。

    MySingletonObject.getInstance()

同伴对象

伴随对象是一种特定类型的对象声明,它允许对象的行为类似于其他语言(如Java)中的静态对象。将companion添加到对象声明允许向对象添加“静态”功能,即使Kotlin中不存在实际的静态概念。这是一个带有实例方法和伴随方法的类的示例。

 class MyClass {
        companion object MyCompanionObject {
            fun actsAsStatic() {
                // do stuff
            }
        }

       fun instanceMethod() {
            // do stuff
        }
    }

调用实例方法看起来像这样。

    var myClass = MyClass()
    myClass.instanceMethod()

调用伴侣对象方法将如下所示。

    MyClass.actsAsStatic()

有关详细信息,请参阅Kotlin docs

答案 1 :(得分:29)

对象可以实现接口。在类中,定义一个不实现任何接口的简单对象在大多数情况下没有任何好处。但是,定义实现各种接口的多个对象(例如Comparator)可能非常有用。

就生命周期而言,伴侣对象与类中声明的命名对象之间没有区别。

答案 2 :(得分:5)

第一次访问时,对象或对象声明会被懒惰地初始化。

在加载相应的类时初始化伴随对象。虽然Kotlin本身并不支持静态成员,但它带来了“静态”本质。

答案 3 :(得分:3)

伴随对象的存在是因为您可以调用伴随对象'函数/属性就像是一个java静态方法/字段。为什么你的Holder被允许,好吧,没有理由声明嵌套对象是非法的。它有时会派上用场。

答案 4 :(得分:0)

伴侣对象在类加载时被初始化(通常是第一次被其他正在执行的代码引用),而 Object 声明则在延迟时初始化。首次访问。

请参阅https://kotlinlang.org/docs/reference/object-declarations.html底部以明确定义这两者之间的区别。

答案 5 :(得分:0)

伴随对象和对象之间唯一的显着区别是可以通过使用包含类的名称直接访问伴随对象的属性和功能。这使它看起来像java静态成员访问。

为什么还可以在类中声明一个普通对象。 考虑以下类,其中的成员对象非常有用。

data class Employee(val name: String) {
    object NameComparator : Comparator<Employee> {
         override fun compare(p1: Employee, p2: Employee): Int =
             p1.name.compareTo(p2.name)
    }
}

现在我们可以将员工列表排序为

list.sortedWith(Employee.NameComparator))