在 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>()
}
}
}
在您的示例中,定义Companion.foo()
是作为成员的扩展。在这种情况下,在与扩展类型相同的类型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>()
}
}
}