最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

kotlin - Type mismatch when using generics with abstract nested classes - Stack Overflow

programmeradmin0浏览0评论

I find an "Argument type mismatch" error in multiply function and don't know how to fix it. The code is:

abstract class Semigroup<T1> {
    abstract val one: SemigroupElement<T1>
    abstract fun builder(x: T1): SemigroupElement<T1>
    abstract val binOp: (SemigroupElement<T1>, SemigroupElement<T1>) -> SemigroupElement<T1>

    abstract inner class SemigroupElement<T1> {
        fun multiply(other: SemigroupElement<T1>) = binOp(this, other)  // Argument type mismatch
        abstract val value: T1
    }
}

I find an "Argument type mismatch" error in multiply function and don't know how to fix it. The code is:

abstract class Semigroup<T1> {
    abstract val one: SemigroupElement<T1>
    abstract fun builder(x: T1): SemigroupElement<T1>
    abstract val binOp: (SemigroupElement<T1>, SemigroupElement<T1>) -> SemigroupElement<T1>

    abstract inner class SemigroupElement<T1> {
        fun multiply(other: SemigroupElement<T1>) = binOp(this, other)  // Argument type mismatch
        abstract val value: T1
    }
}
Share Improve this question edited Feb 1 at 19:34 tyg 16.2k4 gold badges36 silver badges48 bronze badges asked Feb 1 at 18:44 zplotzplot 354 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

When you name all type parameters the same (T1) it becomes confusing.

Let's first rename the type parameter of class Semigroup from T1 to T and the type parameter of class SemigroupElement from T1 to E.

Then you have the following code:

abstract class Semigroup<T> {
    abstract val one : SemigroupElement<T>
    abstract fun builder(x: T): SemigroupElement<T>
    abstract val binOp: (SemigroupElement<T>, SemigroupElement<T>) -> SemigroupElement<T>

    abstract inner class SemigroupElement<E> {
        fun multiply(other: SemigroupElement<E>) = binOp(this, other)  // Argument type mismatch
        abstract val value: E
    }
}

And now it becomes clear why this doesn't work: The abstract binOp requires two SemigroupElement<T>, but you provide it with two SemigroupElement<E>. Since T and E are not related in any way the compiler protests with the error "Type mismatch."

It's not clear what you want to achieve, but it looks like you may not even need a type parameter for SemigroupElement at all. Since SemigroupElement is an inner1 class of the (outer) class Semigroup it can only exist with an instance of Semigroup. Therefore you can access the outer class' type parameter T and let value be of that type:

abstract class Semigroup<T> {
    abstract val one: SemigroupElement
    abstract fun builder(x: T): SemigroupElement
    abstract val binOp: (SemigroupElement, SemigroupElement) -> SemigroupElement

    abstract inner class SemigroupElement {
        fun multiply(other: SemigroupElement) = binOp(this, other)  // This compiles just fine now
        abstract val value: T
    }
}

1: Not nested, as your question title suggests; a nested class wouldn't have the inner modifier, allowing an instance of it even without an instance of the outer class. Here, you have an inner class, not a nested class.
For more see the documentation about Nested and inner classes.

发布评论

评论列表(0)

  1. 暂无评论