Reputation: 2537
I have a custom implementation of a list which returns a new item if none is contained within it.
@Parcelize
class ListOfItems(private val list: Map<String, Item> = mapOf()) : Parcelable {
operator fun get(name: String) = list[name] ?: Item(name)
}
I'd like to use it inside for
loop:
val myListOfItems = ListOfItems(/* ... */)
for (item in myListOfItems)
{
// Do something...
}
How can I achieve it? Is there some interface that I have to implement o some method that I have to add?
Upvotes: 1
Views: 677
Reputation: 7882
As @Jordi noticed, you need to implement Iterable
interface. This could be done even simplier:
class ListOfItems(private val list: Map<String, Item> = mapOf()) : Parcelable, Iterable<Item> by list.values {
operator fun get(name: String) = list[name] ?: Item(name)
}
Moreover, you may implement not Iterable
but Collection
interface (which extends Iterable
) in the same way, taking advantage of various extension members defined for Collection
:
class ListOfItems(private val list: Map<String, Item> = mapOf()) : Parcelable, Collection<Item> by list.values {
operator fun get(name: String) = list[name] ?: Item(name)
}
Or even List
(to make class name consistent with its interface):
class ListOfItems(private val list: Map<String, Item> = mapOf()) : Parcelable, List<Item> by list.values.toList() {
operator fun get(name: String) = list[name] ?: Item(name)
}
Upvotes: 3
Reputation: 2537
In Kotlin, for a class to be used in a for
loop it must implement Iterable<T>
interface.
As per your example:
@Parcelize
class ListOfItems(private val list: Map<String, Item> = mapOf()) : Parcelable, Iterable<Item> {
operator fun get(name: String) = list[name] ?: Item(name)
override fun iterator(): Iterator<Item> = list.values.iterator()
}
Upvotes: 2