为什么/如何工作这个扩展功能?没有"与"怎么称呼它?



在参加"Kotlin for Java Developers"Coursera课程时,我遇到了这种结构,其中包含实例的扩展函数似乎可以访问包含类的私有字段。请注意Data类是如何在Container外部实现的,并且无法访问Container的字段,但Data.printMe()扩展函数可以访问Container的私有containerVal成员:

data class Data (val data: String)
class Container (private val containerVal: String, val data: Data){
fun Data.printMe() {
println("data: $data - in container: ${this@Container.containerVal}")
}
}
fun main() {
val c = Container("mycontainer", Data("mydata"))
// Can I call Data.printMe without using `with`?
// val d = c.data.printMe();
with (c) {
// Prints: data: mydata - in container: mycontainer
data.printMe();
}
}

很酷的是,Data.printMe可以访问Container的私人成员。with(c)显然是允许这样做的原因。我可以看到很多用例,就像在课程示例中,游戏Cell的扩展函数可以访问包含Board,而不会Cell类本身受到Board污染并与紧密耦合。

这种"方法"有名字吗?有没有一种语法可以在不使用with的情况下"直接"调用c.data.printMe?with 文档未提及此用例。

printMe()方法有两个接收方:调度接收方扩展接收方。调度接收器是在其中声明扩展的类的实例,扩展接收器是扩展方法的接收器类型的实例。您是在Container实例(调度接收器)的上下文中访问contaiverVal,而不是在Data实例(扩展接收器)的上下文中访问。

如果您尝试做相反的操作并访问printMe()Data类的私有属性,您将获得编译器错误。

将扩展函数定义为类的成员时,它只能在该类的上下文中使用。您可以在类中或使用 scope 函数访问它,其中上下文对象可用作 lambda 接收器 (this)。这些函数是runwithapply

最新更新