【问题标题】:Kotlin inner class can't resolve extension function declared in outer classKotlin 内部类无法解析外部类中声明的扩展函数
【发布时间】:2021-11-30 05:48:12
【问题描述】:

为什么 Kotlin 中的内部类不能访问外部类中声明的扩展函数如下:

class A{
    val a = "as".foo()      // LINE 1
    class B{
        val b = "as".foo()  // LINE 2
    }

    fun String.foo(){}
}

LINE 1 扩展函数已解析,但LINE 2 函数未解析。想知道为什么会有这样的限制吗?

【问题讨论】:

  • 您是否尝试过将内部类声明为inner class

标签: kotlin kotlin-extension


【解决方案1】:

这不是一个内部类,因为你没有在它上面使用关键字inner。它只是一个嵌套类。如果您熟悉 Java,它就像一个 static 内部类。由于它不是inner,因此它没有对外部类的任何隐式引用,并且由于没有使用其成员的特定实例,因此不能对外部类的成员进行裸调用。但是,它可以在外部类的实例上调用外部类的成员,因此您可以例如执行以下操作:

class A{
    val a = "as".foo()
    class B{
        val b = A().run { "as".foo() }
    }

    fun String.foo(){}
}

尽管foo 是一个扩展函数,但它也是 A 的成员,因为它是在哪里声明的。使用使类成为作用域内的接收者的作用域函数是从另一个类调用其成员扩展函数之一的一种方法。

编辑:这是您希望在类中声明扩展的一个原因示例。

class Sample(val id: Int) {
    private val tag = "Sample#$id"
    fun String.alsoLogged(): String{
        Log.d(tag, this)
        return this
    }
}

您可以使用此扩展轻松记录您在类中使用的字符串(或者当它是runapply 的接收者时)。在类外部声明是没有意义的,因为它使用了该类的私有 tag 属性。

【讨论】:

  • 我明白你的意思,我不明白他们为什么不禁止一个函数在类中被声明为扩展函数?如果类中的扩展函数不能在其范围之外使用,它有什么好处?我只是想了解他们的核心团队在设置此类限制时的想法
  • 你的意思是什么限制?这样的函数只有两个接收器或两个this 对象。它需要同时调用AString。它是允许的,因为它有它的用例。甚至您自己的示例也提供了一个有效的用例 - 您在 A 中使用它作为 "as".foo()。 @法里德
  • 类中的扩展函数可以在其实现中使用该类的成员,这有很多用例。将其声明为公共通常不会有用,但有一些用例,例如在 DSL 中。大多数情况下,您会在类中声明扩展,因为您只想在该类中使用它而不会污染该类外部的命名空间,或者仅仅是因为它会为您在类中执行的某些操作带来更自然的代码其成员。
【解决方案2】:

这是因为 Kotlin 将你的代码编译成

public final class A {
  @NotNull
  private final Unit a;

  @NotNull
  public final Unit getA() {
    return this.a;
  }

  public final void foo(@NotNull String $this$foo) {
    Intrinsics.checkNotNullParameter($this$foo, "$this$foo");
  }

  public A() {
    this.foo("as");
    this.a = Unit.INSTANCE;
  }
  
  public static final class B {
    public B() {
      // You can't access A's foo() method here.
    }
  }
}

【讨论】:

    猜你喜欢
    • 2018-05-25
    • 1970-01-01
    • 2015-09-28
    • 2010-12-02
    • 2014-06-30
    • 1970-01-01
    • 2012-06-13
    • 2013-10-21
    • 1970-01-01
    相关资源
    最近更新 更多