Reputation: 1306
In Kotlin, if I have a function in a companion object with Companion.
as the prefix (Companion.foo
), what difference will it make compared to a foo
inside the companion object?
I noticed that in the following code, Companion.foo
will make it invisible to the outside scope, but still visible to functions inside the same companion object.
You can find the code snippet at: 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")
}
}
}
Are there any other differences? Are A.Companion.foo
and A.foo
the same apart from the visibility? Is this a way to encapsulate methods in the companion object?
Update 1
In my actual project, I'm calling an inline
function from another inline
function in the companion object, which is why access modifiers can't be used. But I still would like to hide foo
if possible.
class C {
companion object {
inline fun <reified T> Companion.foo() {
println("hello in A")
}
inline fun bar() {
foo<String>()
}
}
}
Upvotes: 1
Views: 269
Reputation: 6268
In your example, the definition Companion.foo()
is an extension as a member. In this case you define the extension in the same type A.Companion
as the type of the extension. This is not useful.
The next example shows the concept of an extension as member with two different classes. The example is without companions, because it makes no difference for the concept.
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
}
That all said, the two foo()
function in your example have different signatures internally. The normal function foo()
is a simple method on the companion object without parameters. The extension function Companion.foo()
is a method on the companion object but with an extra parameter for the second this
reference.
To encapsulate methods within companions, just put the private
modifier before the function.
If you need an inline function, use internal
and @PublishedApi
to hide the function from the public API.
class C {
companion object {
@PublishedApi
internal inline fun <reified T> foo() {
println("hello in A")
}
inline fun bar() {
foo<String>()
}
}
}
Upvotes: 2