代码之家  ›  专栏  ›  技术社区  ›  lineage

在嵌套数据类声明中使用外部类的val/方法作为默认值

  •  1
  • lineage  · 技术社区  · 1 年前

    考虑以下玩具示例:

    class A{
        val a=1
    
        fun hello() =println("hello")
    
        init {
            println(a)
            println(this::hello)
        }
    
        data class B(val b: Int = a, val func: () -> Unit = this::hello)
    }
    

    这不会编译,导致错误: Unresolved reference: a 'this' is not defined in this context 。这让我很困惑,因为他们 在前面的内容中可用 init .

    为什么父级的vals/vars/方法在数据类声明中不可访问,即使它是嵌套的?

    尽管有太多的SO问题与“*kotlin*嵌套的*data*”匹配,但我找不到一个答案。

    1 回复  |  直到 1 年前
        1
  •  1
  •   tyg    1 年前

    有两种不同类型的类可以在另一个类中声明:

    • 嵌套类 :这些只是简单的类定义,没有与封闭类的任何连接,只是它们必须用外部类显式限定:

      fun someUnrelatedFunction() {
          val b = A.B()
      }
      

      这就是您所拥有的:两个独立的类、两个独立实例和两个独立 this 物体。因此,您无法访问 外部阶级的。

    • 内部类 :另一方面,内部类只能与 外部类的实例 。这意味着它们不能在自己身上实例化。通常,内部类的对象是由外部类创建的。在 那个 如果外部类的实例可用,并且可以由其他内部类访问:

      class A {
          val a = 1
      
          fun hello() = println("hello")
      
          init {
              println(a)
              println(this::hello)
          }
      
          inner class B(val b: Int = a, val func: () -> Unit = this::hello)
      }
      

      这将立即编译,因为 B 定义为 inner class 。注意,数据类不能是内部类,所以我删除了 data .

      尽管这现在有效,但以下内容不再有效:

      有趣的someUnlatedFunction(){
      val b=A.b()
      }
      

      编译器报告以下错误消息:

      内部类B的构造函数只能用包含类的接收器调用

      相反,您可以在类中创建以下属性 A :

      val b = B()
      

    阅读有关的文档中的更多信息 Nested and inner classes .

    作为结束语,既然你谈到了 父类 在您的问题中:父类只存在于一个类扩展另一个类的继承层次结构中。不过,这是完全无关的,与示例中的代码无关。您的代码是关于 外面的 和一个 内部/嵌套 类,而不是父类和子类。