【问题标题】:Merge methods that return an empty set and an empty list合并返回空集和空列表的方法
【发布时间】:2019-10-25 16:46:01
【问题描述】:

这两个功能很相似

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

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

有什么方法可以将它们组合成一个返回空集或空列表的方法?如果调用者必须传递要返回的空集合,那很好。

理想情况下,我希望在调用者不需要求助于强制转换的情况下实现这一点,即使用asis

【问题讨论】:

  • "如果调用者必须传递要返回的空集合,那很好。"如果他们手头已经有了这个集合,为什么他们需要一个返回它的方法? fun &lt;T&gt; (x: T) = x 在这种情况下可以使用,但这可能不是您想要的。
  • fun &lt;T&gt; empty(): Collection&lt;T&gt; = empty&lt;T&gt;()
  • @QingfeiYuan 我想你的意思是emptyListemptySet 在最后那个表达式中。

标签: generics kotlin


【解决方案1】:

不可能同时返回两种类型。您必须以某种方式确定它。

来自ListSet

您可以创建一个extention function,从现有集合创建一个空集合。

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()

【讨论】:

    【解决方案2】:

    您可以创建一个同时实现List&lt;E&gt;Set&lt;E&gt; 的接口:

    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()
    

    【讨论】:

      【解决方案3】:

      可能是这样的:

      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()
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-09-12
        • 1970-01-01
        • 2010-09-25
        • 2018-02-13
        • 1970-01-01
        • 1970-01-01
        • 2020-11-06
        相关资源
        最近更新 更多