在同伴对象中包含Companion.foo有什么区别?

时间:2019-10-15 04:49:53

标签: kotlin kotlin-companion

在Kotlin中,如果我在带有Companion.作为前缀(Companion.foo的同伴对象中有一个函数,与同伴对象内的foo相比有什么区别?

我注意到在下面的代码中,Companion.foo将使其对外部作用域不可见,但对于同一同伴对象内部的函数仍然可见。

您可以在以下位置找到代码段:https://pl.kotl.in/t6FvM6ni6

fun main() {
    A.foo() // compiler complains "unresolved reference"
    A.bar()
    B.foo()
}

class A {
    companion object {
        fun Companion.foo() {
            println("hello in A")
        }

        fun bar() {
            foo()
        }
    }
}

class B {
    companion object {
        fun foo() {
            println("hello in B")
        }
    }
}

还有其他区别吗? A.Companion.fooA.foo的可见性是否相同?这是一种将方法封装在伴随对象中的方法吗?


更新1

在我的实际项目中,我从同伴对象中的另一个inline函数调用一个inline函数,这就是为什么不能使用访问修饰符的原因。但是,如果可能的话,我仍然想隐藏foo

class C {
    companion object {
        inline fun <reified T> Companion.foo() {
            println("hello in A")
        }

        inline fun bar() {
            foo<String>()
        }
    }
}

1 个答案:

答案 0 :(得分:2)

在您的示例中,定义Companion.foo()extension as a member。在这种情况下,您可以使用与扩展名相同的类型A.Companion来定义扩展名。这没用。

下一个示例显示了具有两个不同类的成员扩展的概念。该示例没有附带内容,因为它对概念没有影响。

class A 

class B {
    fun A.foo() {
        println("Extension for A, only visible in B")
        println("Function has two 'this' references: ${this} and ${this@B}")
    }

    fun bar() {
        val a = A()
        a.foo() // this function call is only possible in the context of `B`
    }
}

fun main() {
    val a = A()
    a.foo() // compile error
}

总而言之,示例中的两个foo()函数内部具有不同的签名。普通函数foo()是对不带参数的伴随对象的一种简单方法。扩展功能Companion.foo()是伴随对象上的一种方法,但具有用于第二个this引用的额外参数。

要将方法封装在同伴中,只需将private修饰符放在函数之前。

如果需要内联函数,请使用internal@PublishedApi从公共API隐藏该函数。

class C {
    companion object {
        @PublishedApi
        internal inline fun <reified T> foo() {
            println("hello in A")
        }

        inline fun bar() {
            foo<String>()
        }
    }
}