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

admin2025-04-16  3

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 edited Feb 1 at 19:34 tyg 16.7k4 gold badges38 silver badges49 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.

转载请注明原文地址:http://anycun.com/QandA/1744819090a88051.html