kotlin 尝试获取类中匿名类的成员时无法解析的引用

tzdcorbm  于 2023-10-23  发布在  Kotlin
关注(0)|答案(2)|浏览(146)
class A{
    val b = object{
        val x = 1
    }
}

fun main() {
    val y = A()
    println(y.b.x)
}

我希望看到1,但我得到Unresolved reference: x出于某种原因。为什么

xzlaal3s

xzlaal3s1#

类只有在有名称的情况下才能是类型。这就是语言的定义。
当你宣布

val x = "Hello"

它简称为

val x: String = "Hello"

当你宣布

val x = object { }

它简称为

val x: Any = object { }

因为匿名类的类型是Any,或者是它实现的接口之一。没有短语可以作为匿名类的类型,因为您还没有定义任何短语来命名它(因此使用了单词anonymous)。你提到了A$b$1,但它不是一个命名类型,也不是有效的代码,因为它是未定义的。这只是调试器用来标识它的东西。
”““这不是缺点。匿名对象是我们可以 * 封装 * 代码的方式之一。
有一种特殊的情况,编译器允许你直接访问匿名对象的成员,如果你在声明对象的同一个范围内,并且它被分配给局部变量或私有属性。在最初的问题中,您没有从声明属性的范围内访问属性,并且它不是私有的。这是一种奇怪的情况,因为财产的类型变得模糊。你不能输入它的名字,也不能重新分配它,即使它是一个var。

bcs8qyzn

bcs8qyzn2#

当您执行val b = object { ... }时,b将具有Any类型。所以,这实际上等同于

val b: Any = object { ... }

当你使用b时,你只知道它是Any的一个示例,它没有任何名为x的属性。同样的事情也适用于普通类,例如:

fun main() {
    val string: Any = "some string"
    string.length // compilation error, even though length is defined for String
}

你可以做的是在直接与匿名类示例交互时使用该字段:

fun main() {
    val xValue = object {
        val x = 1
    }.x
    println(xValue) // prints 1
}

如果这不是特别有用,你必须定义一个类型来告诉编译器在该示例上使用某个属性是安全的:

interface MyInterface {
    val x: Int
}

fun main() {
    val instance = object : MyInterface {
        override val x = 1
    }
    println(instance.x) // prints 1
}

或者,您可以始终使用反射,假设属性x在运行时存在:

import kotlin.reflect.full.declaredMemberProperties

class A {
    val b = object {
        val x = 1
    }
}

fun main() {
    val anonymousClassInstance = A().b
    val property = anonymousClassInstance::class.declaredMemberProperties.find { it.name == "x" }
        ?: throw IllegalArgumentException("...")

    val value = property.getter.call(anonymousClassInstance)
    println(value) // prints 1
}

相关问题