匿名对象的kotlin访问属性

时间:2019-05-07 11:16:28

标签: kotlin

如何访问匿名对象的对象的属性word

 fun main(args: Array<String>) {

        val sentence = "this is a nice sentence"

        val wordLengths: List<Any> = sentence.split(' ').map {
            object {
                val length = it.length
                val word = it
            }
        }

        wordLengths.forEach { it:Any -> println(it) }
    }

2 个答案:

答案 0 :(得分:2)

您明确声明wordLengthsList<Any>,并且Any没有wordlength属性。您应该让Kotlin从map推断类型。

fun main() {
    val sentence = "This is a nice sentence"

    val wordLengths = sentence.split(' ').map {
        object {
            val word = it
            val length = it.length
        }
    }

    wordLengths.forEach {
        println("[${it.length}] ${it.word}")
    }
}

如果您打算在方法之外使用此对象,则应创建必要的类或使用现有的类(例如PairString本身)。参见Object expressions

  

请注意,匿名对象只能在本地和私有声明中用作类型。如果您将匿名对象用作公共函数的返回类型或公共属性的类型,则该函数或属性的实际类型将是该匿名对象的声明超类型,或者如果没有,则为Any声明任何超类型。添加到匿名对象中的成员将不可访问。

答案 1 :(得分:1)

可以使其按预期工作,但这可能不是一个好方法。

当前的问题是代码将wordLengths的类型指定为List<Any>Any是顶部类型*;每个类型都是它的子类型,因此您只能安全地访问每个类型具有的内容(例如toString()方法)。

但是,您不需要指定类型;您可以将其留给Kotlin的类型推断。如果这样做,它将推断您使用object关键字定义的类型。该类型是匿名的-您不能写下它的名称-但Kotlin知道它,并且可以访问其字段:

fun main() {
    val sentence = "this is a nice sentence"

    val wordLengths = sentence.split(' ').map {
        object {
            val length = it.length
            val word = it
        }
    }

    wordLengths.forEach{ println(it.word) }
}

也就是说,它有点笨拙和脆弱。您最好为类型定义一个类。实际上,总的来说较短:

fun main2() {
    val sentence = "this is a nice sentence"

    class Word(val length: Int, val word: String)

    val wordLengths = sentence.split(' ').map{ Word(it.length, it) }

    wordLengths.forEach { println(it.word) }
}

(实际上,您可能想在其他地方使用新类,然后将其移到方法之外。但是Kotlin允许您定义本地类。)

———

(*实际上,顶部类型是可空的Any:Any?。但是我忽略了可空性,因为它与此无关。)