我想定义一个通用代数数据类型以与我的 parse
函数一起使用,如下所示:
sealed class Result<T> {
class Success(val value: T, val pos: Int) : Result<T>()
class Failure(val message: String, val pos: Int) : Result<T>()
}
fun <T> parse(t: Parser<T>, input: String, initialPos: Int = 0, collectErrors: Boolean = true) : Result<T> {
然而,这是不允许的,因为
T
是一个 undefined reference 。如果我将
T
添加到所有成员类型,它会起作用:sealed class Result<T> {
class Success<T>(val value: T, val pos: Int) : Result<T>()
class Failure<T>(val message: String, val pos: Int) : Result<T>()
}
对我来说,这有点令人困惑,这让我相信我在这里遗漏了一些东西。为什么在第一种情况下定义成员类型时没有看到
T
?此外,在创建
Success
实例时,我希望语法为:Result<T>.Success<T>(tv.someValue, pos)
但这行不通,我这样做:
Result.Success<T>(tv.someValue, pos)
这对我来说是更可取的语法,但我很难理解为什么我应该在这里省略 Result 上的
T
。
最佳答案
Result
是一个泛型类,有一个名为 T 的泛型参数。不过类名是 Result
,而不是 Result<T>
。Success
也是一个泛型类。因此,由于它是通用的,您需要将其定义为 Success<T>
。如果你不这样做,那么它就不再是通用的了。请注意,即使它是泛型 Result 的子类,它也可能是非泛型类型。例如:
class Success(val value: String, val pos: Int) : Result<String>()
还要注意,虽然 Result 和 Failure 是通用的,但它们不会将它们的通用类型用于任何事情。所以你实际上可以将你的类定义为
sealed class Result {
class Success<T>(val value: T, val pos: Int) : Result()
class Failure(val message: String, val pos: Int) : Result()
}
现在,为什么需要使用
Result.Success<T>(tv.someValue, pos)
而不是 Result<T>.Success<T>(tv.someValue, pos)
?因为类的名称是
Result.Success
。参数类型不是类名的一部分。大多数时候,根本没有必要指定它,因为它会被推断:val r = Result.Success("foo", 1)
创建
Success<String>
的一个实例。如果你想创建一个 Success<CharSequence>
,那么你必须明确指定泛型类型:val r = Result.Success<CharSequence>("foo", 1)
或者
val r: Result.Success<CharSequence> = Result.Success("foo", 1)
关于generics - 为什么通用代数数据类型需要 `T` 成员类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38029391/