使用一个对象来实现一个空List的错误

我试图重写列表接口作为学习function编程Kotlin的练习,但我无法弄清楚为什么我得到一个错误,当我试图让一个对象作为空的列表,在Kotlin标准库中不会发生。 在我的代码中,见下面,我想使用NIL作为单例空列表,使用list()作为函数返回它。 但是,这会在types为“必需列表”的函数上生成types不匹配错误。findNIL“

interface List { val empty: Boolean val head: A val tail: List fun cons(a: A): List = Cons(a, this) } object NIL : List { override val empty: Boolean = true override val head: Nothing get() = throw IllegalStateException("head called on empty list") override val tail: List get() = throw IllegalStateException("tail called on empty list") } private class Cons(override val head: A, override val tail: List) : List { override val empty: Boolean = false } fun  list(): List = NIL // Type mismatch. Required: List. Found: NIL fun  list(vararg a: A): List { var n = list() for (e in a.reversed()) { n = Cons(e, n) } return n } 

在标准库中,这个错误不会发生,正如您可以在Collections.kt的EmptyList中看到的一样 。 我做错了什么,或者我错过了一些让后者成为可能的概念,而前者不是?

评估提出的解决方案

在所提出的三种解决方案中,唯一允许通过下面的测试代码的是使用匿名对象的 ,而其他的则抛出exceptionjava.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Void

 assertEquals("a", list().cons("a").head) 

但是,如果将NIL更改为NIL : List ,则解决方案NIL as List可以毫无问题地工作。

您可以通过as关键字将List List转换为List ,例如:

 fun  list(): List = NIL as List; 

如果你想压制编译器警告,你可以使用@Suppress注解来注释这个函数,例如:

 @Suppress("UNCHECKED_CAST") fun  list(): List = NIL as List; 

或者如果你不喜欢这种方式,你可以在一个函数中使用一个匿名对象 ,例如:

 fun  list(): List = object : List { override val empty: Boolean = true override val head: A get() = throw IllegalStateException("head called on empty list") override val tail: List get() = throw IllegalStateException("tail called on empty list") }; 

通用接口应该是而不是

另外,IntelliJ Idea在这种情况下使用generics时会显示一个警告。