Методы слияния, которые возвращают пустой набор и пустой список - PullRequest
0 голосов
/ 25 октября 2019

Эти две функции очень похожи

fun <T> emptyList(): List<T> = emptyList<T>()

fun <T> emptySet(): Set<T> = emptySet<T>()

Есть ли способ, которым они могут быть объединены в один метод, который возвращает либо пустой набор, либо пустой список? Если вызывающий должен передать пустую коллекцию, которая будет возвращена, это было бы хорошо.

В идеале я хотел бы достичь этого без того, чтобы вызывающему абоненту приходилось прибегать к кастингу, то есть с использованием as или is.

Ответы [ 3 ]

0 голосов
/ 25 октября 2019

Вы можете создать интерфейс, который реализует List<E> и Set<E>:

interface ListSet<out E> : List<E>, Set<E> {
    // Must override this fun because it's defined in `List` and `Set`
    override fun spliterator(): Spliterator<@UnsafeVariance E>
}

Теперь вы можете вернуть его экземпляр из вашей функции:

private object EmptyListSet :
    ListSet<Nothing>,
    List<Nothing> by emptyList(),
    Set<Nothing> by emptySet() {
    override fun spliterator(): Spliterator<Nothing> = emptyList<Nothing>().spliterator()
    // Must override following elements because they can be delegated to `List` and `Set`
    override val size: Int get() = 0
    override fun contains(element: Nothing) = false
    override fun containsAll(elements: Collection<Nothing>) = false
    override fun isEmpty() = true
    override fun iterator() = emptyList<Nothing>().iterator()
}

fun <E> emptyListSet(): ListSet<E> = EmptyListSet

Варианты использования:

val list: List<Int> = emptyListSet()
val set: Set<String> = emptyListSet()
0 голосов
/ 26 октября 2019

Может быть, что-то вроде этого:

import kotlin.reflect.KClass

fun main() {
    val emptyList = emptyCollection(List::class)
    val emptySet = emptyCollection(Set::class)
}

fun <T: Collection<*>> emptyCollection(clazz: KClass<T>): Collection<Nothing> {
    return when (clazz) {
        List::class -> emptyList<Nothing>()
        Set::class -> emptySet<Nothing>()
        else -> throw IllegalArgumentException()
    }
}
0 голосов
/ 25 октября 2019

Невозможно вернуть два типа одновременно. Вы должны определить это каким-либо образом.

Из List или Set

Вы можете создать функцию расширения , которая создастпустая коллекция из существующей.

fun <T> List<T>.empty() = emptyList<T>()
fun <T> Set<T>.empty() = emptySet<T>()

Из этого вы можете использовать ее как любую другую функцию списка / набора.

val emptyList: List<Int> = listOf(1,2).empty()

Будьте осторожны. Это не преобразует текущий список. Он просто создает новый пустой.

Из неизвестной коллекции, такой как Iterator

Чистый Iterable без верхнего класса:

fun <T> empty() = object : Iterable<T> {
    override fun iterator(): Iterator<T> = object : Iterator<T> {
        override fun hasNext(): Boolean = false
        override fun next(): T = throw IllegalStateException("No Item")
    }
}

Вы можете использовать ужеопределенная функция Iterable.toSet() и Iterable.toList()

val emptyList: List<Int> = empty<Int>().toList()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...