如何将泛型封闭类和接口中的主 `T` 和子 `T` 强制转换为类型约束?

huangapple go评论111阅读模式
英文:

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&lt;Collection&gt; {
    fun merge(with: Collection?)
}
sealed class CollectionType&lt;T: MergeableCollection&lt;*&gt;&gt; {
    // no data cases
    class none&lt;T: MergeableCollection&lt;*&gt;&gt;: CollectionType&lt;T&gt;()
    class standard&lt;T: MergeableCollection&lt;*&gt;&gt;: CollectionType&lt;T&gt;()
    // data case
    data class data&lt;T: MergeableCollection&lt;*&gt;&gt;(val values: T?): CollectionType&lt;T&gt;()

    fun &lt;T: MergeableCollection&lt;*&gt;&gt; finalCollection(standard: T): T? {
        if (this is none) { return null }
        if (this is data) {
            if (values != null) {
                standard.merge(with = values)  &lt;&lt; *** `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&#39;ve made a complete mess of the type hierarchy. What I *think* you&#39;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&#39;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&lt;&gt;` 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&lt;T&gt; {
    fun merge(with: T?)
}
sealed class CollectionType&lt;T: MergeableCollection&lt;*&gt;&gt; {
    // no data cases
    class none&lt;T: MergeableCollection&lt;T&gt;&gt;: CollectionType&lt;T&gt;()
    class standard&lt;T: MergeableCollection&lt;T&gt;&gt;: CollectionType&lt;T&gt;()
    // data case
    data class data&lt;T: MergeableCollection&lt;T&gt;&gt;(val values: T?): CollectionType&lt;T&gt;()

    fun &lt;T: MergeableCollection&lt;T&gt;&gt; finalCollection(standard: T): T? {
        if (this is none) { return null }
        if (this is data) {
            if (values != null) {
                standard.merge(with = values as T?) // &lt;&lt; CASTING
                return standard
            } else {
                return standard
            }
        } else {
            return standard
        }
    }
}
英文:

I simply solved it like that:
1- each sub class constrains their MergeableCollection&lt;&gt; 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&lt;T&gt; {
    fun merge(with: T?)
}
sealed class CollectionType&lt;T: MergeableCollection&lt;*&gt;&gt; {
    // no data cases
    class none&lt;T: MergeableCollection&lt;T&gt;&gt;: CollectionType&lt;T&gt;()
    class standard&lt;T: MergeableCollection&lt;T&gt;&gt;: CollectionType&lt;T&gt;()
    // data case
    data class data&lt;T: MergeableCollection&lt;T&gt;&gt;(val values: T?): CollectionType&lt;T&gt;()

    fun &lt;T: MergeableCollection&lt;T&gt;&gt; finalCollection(standard: T): T? {
        if (this is none) { return null }
        if (this is data) {
            if (values != null) {
                standard.merge(with = values as T?) // &lt;&lt; CASTING
                return standard
            } else {
                return standard
            }
        } else {
            return standard
        }
    }
}

huangapple
  • 本文由 发表于 2023年6月12日 17:27:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76455263.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定