在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.foo
和A.foo
的可见性是否相同?这是一种将方法封装在伴随对象中的方法吗?
更新1
在我的实际项目中,我从同伴对象中的另一个inline
函数调用一个inline
函数,这就是为什么不能使用访问修饰符的原因。但是,如果可能的话,我仍然想隐藏foo
。
class C {
companion object {
inline fun <reified T> Companion.foo() {
println("hello in A")
}
inline fun bar() {
foo<String>()
}
}
}
答案 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>()
}
}
}