在Kotlin语言中,这个语法是做什么的,它是如何工作的?
class ClassName1 {
companion object {
fun ClassName2.funName()=""
}
}
class ClassName1 {
companion object {
fun ClassName2.funName()=""
}
}
object
,可以通过仅使用类名来引用。class ClassName1 {
fun method(): String {
val something = ClassName2()
return something.funName()
}
companion object {
fun ClassName2.funName() = ""
}
}
然而,这种用法并不要求函数必须是公开的。
另一种使用方式是将伴生对象作为一种范围的方式:
val something = ClassName2()
with(ClassName1) { // this: ClassName1.Companion
something.funName() // brought in scope by ClassName1's companion
}
或者,如果你从伴侣中导入该功能,则可以直接使用:
import ClassName1.Companion.funName
val something = ClassName2()
something.funName()
Duration.Compaion
,用于定义数字类型的扩展(这些是扩展属性,但其实是相同的思想):
https://github.com/JetBrains/kotlin/blob/6a670dc5f38fc73eb01d754d8f7c158ae0176ceb/libraries/stdlib/src/kotlin/time/Duration.kt#L71
funName()
函数是由method()
调用的。你是错过了它还是在寻找其他东西? - JoffreyClassName1
之外调用它取决于其可见性。当然,如果可见性允许,你仍然需要导入它。当可见性为“private”时,在类中声明和在伴生对象中声明之间仍然存在差异。当在伴生对象中声明时,函数体无法访问类成员,这有时可能是期望的,以表达该函数是纯函数。 - Joffrey这是一种奇怪的语法。使用此语法的一个例子可以是:
import ClassName1.Companion.funName
class ClassName1 {
companion object {
fun ClassName2.funName() = ""
}
}
class ClassName2
fun main() {
ClassName2().funName()
}
这里我需要从Class1.Companion
导入funName
才能调用它。没有简单的方法可以调用此函数。
如果您没有使用扩展函数的经验,可以查看反编译的字节码以了解底层发生了什么:
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
是在ClassName1
中声明的静态Companion
类内部的一个函数。它接收一个ClassName2
对象作为参数(这就是扩展函数的工作原理,没有什么特别之处)。ClassName2
对象似乎是一种更清晰的方法。