我想定义一个通用代数数据类型,用于我的[
[ task_1, task_2, task_3 ],
[ task_4, task_5 ]
]
函数,如下所示:
renderTasks() {
let filteredTasks = this.props.tasks;
let taskRows = filteredTasks.reduce(function (rows, task, i) {
let rowIndex = Math.floor(i / 3);
if (i % 3 == 0) {
rows[rowIndex] = [task]
} else {
rows[rowIndex].push(task)
}
return rows;
}, []);
return taskRows.map(this.renderTasksRow);
}
renderTasksRow(rowTasks) {
return <Row>{rowTasks.map(this.renderTask)}</Row>;
}
renderTask(task) {
const currentUserId = this.props.currentUser && this.props.currentUser._id;
const showPrivateButton = task.owner === currentUserId;
return (
<Task
key={task._id}
task={task}
showPrivateButton={showPrivateButton}
/>
);
}
然而,这是不允许的,因为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
对我而言,这有点令人困惑,这让我相信我在这里错过了一些东西。在第一种情况下定义成员类型时,为什么没有看到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)
。
答案 0 :(得分:6)
Result
是一个泛型类,有一个名为T的通用参数。但是,类名称为Result
,而不是Result<T>
。
Success
也是一个通用类。因此,由于它是通用的,您需要将其定义为Success<T>
。如果你不这样做,那么它就不再是通用了。请注意,尽管它是Result的子类,它是通用的,但它可能是非泛型类型。例如:
class Success(val value: String, val pos: Int) : Result<String>()
另请注意,虽然结果和失败是通用的,但它们不会将任何通用类型用于通用类型。所以你实际上可以将你的类定义为
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)
答案 1 :(得分:4)
规则与Java中的规则相同。它基本上归结为Success
和Failure
是Result
的静态嵌套类。没有&#34;成员类型&#34;在Kotlin中,静态嵌套类是可以访问外部类范围的常规类。如果一个类扩展了泛型超类,它总是需要绑定泛型类型参数。
相反,非静态嵌套类(由inner
关键字表示)始终带有外部类的泛型类型参数。这样,您可以构造以下类型层次结构:
open class Foo<T> {
inner class Bar : Foo<T>()
}
要实例化Bar
,您需要拥有Foo
的实例:
val b = Foo<String>().Bar()
答案 2 :(得分:1)
如果你使用像这样的out方差
,它应该有效sealed class Result<out T> {
data class Success<out T>(val value: T, val pos: Int) : Result<T>()
data class Failure(val message: String, val pos: Int) : Result<Nothing>()
}
答案 3 :(得分:0)
在您的示例中,有三个不同的通用参数,而不是一个。即你的代码相当于:
sealed class Result<I> {
class Success<A>(val value: A, val pos: Int) : Result<A>()
class Failure<B>(val message: String, val pos: Int) : Result<B>()
}
但是其他答案如何提及,您不使用I
和B
参数,因此最好省略它们。