Reputation: 2314
How do I access the property word
of the object of the anonymous object
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) }
}
Upvotes: 2
Views: 2647
Reputation: 18567
This can be made to work as intended — but it's probably not a good approach.
The immediate issue is that the code specifies the type of wordLengths
as List<Any>
. Any
is the top type*; every type is a subtype of it, and so you can only safely access things that every type has (such as the toString()
method).
However, you don't need to specify the type; you can leave that to Kotlin's type inference. If you do, it infers the type that you've defined with the object
keyword. That type is anonymous — you can't write down its name — but Kotlin knows about it, and can access its fields:
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) }
}
That said, it's a bit awkward and fragile. You'd be better off defining a class for the type. In fact, that's shorter overall:
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) }
}
(In practice, you'd probably want to use the new class elsewhere, and move it outside the method. But Kotlin lets you define local classes if you need to.)
———
(* Actually, the top type is nullable Any: Any?
. But I'm ignoring nullability as it's not relevant to this.)
Upvotes: 1
Reputation: 45806
You are explicitly declaring wordLengths
to be List<Any>
, and Any
doesn't have a word
or length
property. You should let Kotlin infer the type from 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}")
}
}
If you plan on needing this object outside of the method then you should create the necessary class or use an existing class (e.g. Pair
or String
itself). See Object expressions:
Note that anonymous objects can be used as types only in local and private declarations. If you use an anonymous object as a return type of a public function or the type of a public property, the actual type of that function or property will be the declared supertype of the anonymous object, or
Any
if you didn't declare any supertype. Members added in the anonymous object will not be accessible.
Upvotes: 6