In Kotlin language, what does this syntax do and how does it work ?
class ClassName1 {
companion object {
fun ClassName2.funName()=""
}
}
CodePudding user response:
There are multiple things at play here:
- extension functions: they allow to use the function as if it were part of the receiver type (the type on the left of the function name)
- extension functions used as members: extension functions that can be used on their receiver (known as extension receiver) only when the enclosing class (the dispatch receiver) is in scope
- companion objects: a special
object
that is associated to a class and can be referenced by just using the class name
Declaring a member extension function inside a companion object might be useful for different things.
For instance, such function can be used within the class as if the extension function was declared as a class member but outside the companion. Some people prefer to put them in the companion object to make it clear that they don't depend on the state of said class (like a Java static function):
class ClassName1 {
fun method(): String {
val something = ClassName2()
return something.funName()
}
companion object {
fun ClassName2.funName() = ""
}
}
Such use doesn't require the function to be public, though.
Another way to use this would be by using the companion object as a sort of scope:
val something = ClassName2()
with(ClassName1) { // this: ClassName1.Companion
something.funName() // brought in scope by ClassName1's companion
}
Or directly if you import the function from the companion:
import ClassName1.Companion.funName
val something = ClassName2()
something.funName()
Such pattern is used for instance for Duration.Compaion
to define extensions on number types (those are extension properties but it's the same idea):
https://github.com/JetBrains/kotlin/blob/6a670dc5f38fc73eb01d754d8f7c158ae0176ceb/libraries/stdlib/src/kotlin/time/Duration.kt#L71
CodePudding user response:
This is a weird syntax. One example to use this can be:
import ClassName1.Companion.funName
class ClassName1 {
companion object {
fun ClassName2.funName() = ""
}
}
class ClassName2
fun main() {
ClassName2().funName()
}
Here I had to import funName
from Class1.Companion
in order to call it. There's no easy way to call this function.
If you don't have past experience with extension functions, you can take a look at the decompiled bytecode to see what's happening under the hood:
public final class ClassName2 {
}
public final class ClassName1 {
@NotNull
public static final ClassName1.Companion Companion = new ClassName1.Companion((DefaultConstructorMarker)null);
public static final class Companion {
@NotNull
public final String funName(@NotNull ClassName2 $this$funName) {
return "";
}
private Companion() {
}
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
public final class YourFileNameKt {
public static final void main() {
ClassName1.Companion.funName(new ClassName2());
}
}
funName
is a function inside static Companion
class declared inside ClassName1
. It receives a ClassName2
object as a parameter (this is how extension functions work, nothing special here).
But I would say that this type of declaration is very confusing. It would be better if you could provide more info on how this is being used in your case. Passing a ClassName2
object directly in the function seems to be a much cleaner approach here.