匿名对象的方法范围-Kotlin

时间:2019-05-24 12:43:48

标签: kotlin

在Kotlin中,如果我在匿名对象上定义一个方法,有时我可以访问它,而其他时候则不能。这似乎与范围规则有关,但是我不确定是什么。

在下面的代码示例中,对example3.field.method()的访问将导致编译错误。有趣的是,example2.field.method()可以很好地编译。

以下行为的解释可能是什么?

class Example3 {
    val field = object {
        fun method() {}
    }
}

fun showcase() {
    val example1 = object {
        fun method() {}
    }
    example1.method()
    println(example1::class.qualifiedName)

    class Example2 {
        val field = object {
            fun method() {}
        }
    }

    val example2 = Example2()
    example2.field.method()
    println(example2::class.qualifiedName)

    val example3 = Example3()
    // example3.field.method()  // won't compile
    println(example3::class.qualifiedName)
}

2 个答案:

答案 0 :(得分:5)

来自文档Object Expressions and Declarations

  

请注意,匿名对象只能在本地和本地用作类型   私人声明。如果您使用匿名对象作为返回类型   公共职能或公共财产的类型,实际类型   该函数或属性的,将是的已声明超类型   匿名对象,或者Any(如果您未声明任何超类型)。 会员   添加到匿名对象中的对象将无法访问。

在下面的代码示例中演示:

class Example4{
    val publicObj = object{
        val x = 1
    }

    private val privateObj = object{
        val x = 2
    }

    fun showcase(){
        val scopedObj = object{
            val x = 3
        }
        println(publicObj.x)    // ERROR : unresolved reference: x
        println(privateObj.x)   // OK
        println(scopedObj.x)    // OK
    }
}

答案 1 :(得分:2)

Pawel给出了正确的答案,指向文档:

  

该函数或属性的实际类型将是匿名对象的声明的超类型;如果未声明任何超类型,则为Any。

但是要补充一点,如果您确实需要访问example3.field.method(),则可以在field中为Example3声明一个超类型:

interface MyInterface {
    fun method()
}

class Example3 {
    val field = object: MyInterface { 
        override fun method() {} 
    }
}

fun main() {
    val example3 = Example3()
    example3.field.method()
}