英文:
How to cast main and sub `T` in generic sealed class and interface as type constraint?
问题
这是一个封闭类,充当带有关联值的枚举,限制可接受的类型为实现接口的类型,该接口包含封闭类应执行的函数:merge
。
问题在于在函数使用处,预编译器声称存在类型不匹配
问题:« 需要: Nothing? 找到: T & Any »。
虽然将values
转型为T.Collection
听起来很自然,但我不知道在Kotlin中如何表达,特别是因为自动补全对T
没有任何提案,而要求一个Nothing
?
interface MergeableCollection<Collection> {
fun merge(with: Collection?)
}
sealed class CollectionType<T: MergeableCollection<*>> {
// 无数据情况
class none<T: MergeableCollection<*>>: CollectionType<T>()
class standard<T: MergeableCollection<*>>: CollectionType<T>()
// 数据情况
data class data<T: MergeableCollection<*>>(val values: T?): CollectionType<T>()
fun <T: MergeableCollection<*>> finalCollection(standard: T): T? {
if (this is none) { return null }
if (this is data) {
if (values != null) {
standard.merge(with = values) // *** `类型不匹配` ***
return standard
} else {
return standard
}
} else {
return standard
}
}
}
英文:
Here's a sealed class acting as an enum with associated values that constrains acceptable types to those implementing an interface holding a function that the sealed class should perform: merge
The problem is that at the function usage site, the pre-compiler claims a Type mismatch
« Required: Nothing? Found: T & Any ».
Although it sounds 'natural' to have to cast values
to T.Collection
I have no idea how to say that in kotlin especially since the auto-completion doesn't propose anything on T
and requests a Nothing
?
interface MergeableCollection<Collection> {
fun merge(with: Collection?)
}
sealed class CollectionType<T: MergeableCollection<*>> {
// no data cases
class none<T: MergeableCollection<*>>: CollectionType<T>()
class standard<T: MergeableCollection<*>>: CollectionType<T>()
// data case
data class data<T: MergeableCollection<*>>(val values: T?): CollectionType<T>()
fun <T: MergeableCollection<*>> finalCollection(standard: T): T? {
if (this is none) { return null }
if (this is data) {
if (values != null) {
standard.merge(with = values) << *** `Type mismatch` ***
return standard
} else {
return standard
}
} else {
return standard
}
}
}
答案1
得分: 1
你已经完全混乱了类型层次结构。我认为你试图做的是这样的:
密封接口 MergeableCollection<T> {
fun merge(with: MergeableCollection<T>): MergeableCollection<T>
}
class None<T> : MergeableCollection<T> {
override fun merge(other: MergeableCollection<T>) = other
}
class Standard<T>(val values: List<T>) : MergeableCollection<T> {
// TODO 这可能有一个包含一些T的字段,用于合并实现
}
// 我不确定 Colors 的具体实现是什么
```这样,你就不需要`is`检查,实现类会提供它们。
<details>
<summary>英文:</summary>
You've made a complete mess of the type hierarchy. What I *think* you're trying to do is this:
sealed interface MergeableCollection<T> {
fun merge(with: MergeableCollection<T>): MergeableCollection<T>
}
class None<T> : MergeableCollection<T> {
override fun merge(MergeableCollection<T> other) = other
}
class Standard<T>(val values: List<T>) : MergeableCollection<T> {
// TODO this probably has a field containing some T's that's used in the merge implementation
}
// I'm not sure what the Colors specific implementation is for
This way, you don't need the `is` checks, the implementation classes provide them.
</details>
# 答案2
**得分**: 0
I simply solved it like that:
1- each sub class constrains their `MergeableCollection<>` to `T` rather than `*`
2- `values` is casted to `T?`
It works perfectly.
Thanks all to your question (especially @Jorn) that directed me toward the solution.
```kotlin
interface MergeableCollection<T> {
fun merge(with: T?)
}
sealed class CollectionType<T: MergeableCollection<*>> {
// no data cases
class none<T: MergeableCollection<T>>: CollectionType<T>()
class standard<T: MergeableCollection<T>>: CollectionType<T>()
// data case
data class data<T: MergeableCollection<T>>(val values: T?): CollectionType<T>()
fun <T: MergeableCollection<T>> finalCollection(standard: T): T? {
if (this is none) { return null }
if (this is data) {
if (values != null) {
standard.merge(with = values as T?) // << CASTING
return standard
} else {
return standard
}
} else {
return standard
}
}
}
英文:
I simply solved it like that:
1- each sub class constrains their MergeableCollection<>
to T
rather than *
2- values
is casted to T?
It works perfectly.
Thanks all to your question (especially @Jorn) that directed me toward the solution.
interface MergeableCollection<T> {
fun merge(with: T?)
}
sealed class CollectionType<T: MergeableCollection<*>> {
// no data cases
class none<T: MergeableCollection<T>>: CollectionType<T>()
class standard<T: MergeableCollection<T>>: CollectionType<T>()
// data case
data class data<T: MergeableCollection<T>>(val values: T?): CollectionType<T>()
fun <T: MergeableCollection<T>> finalCollection(standard: T): T? {
if (this is none) { return null }
if (this is data) {
if (values != null) {
standard.merge(with = values as T?) // << CASTING
return standard
} else {
return standard
}
} else {
return standard
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论