2

I have the following abstract class

abstract class Vec2t<T : Number>(open var x: T, open var y: T)

implemented by

data class Vec2(override var x: Float, override var y: Float) : Vec2t<Float>(x, y)

So far, everything works just fine

Now, I'd like to do something similar for the matrices, this is at the moment my abstract class

abstract class Mat2t<T : Number>(open var value: Array<out Vec2t<T>>)

that should be implemented by

class Mat2(override var value: Array<Vec2>) : Mat2t<Float>(value)

But compiler complains on Array<Vec2>:

Error:(8, 32) Kotlin: Type of 'value' doesn't match the type of the overridden var-property 'public open var value: Array> defined in main.mat.Mat2t'

I was told:

  • I can't change the type of a var property when I override it (but actually I am not really changing it, I am overriding it with a subtype.. is it the same thing?)
  • mat2.value = object : Vec2t<Float>() { ... } would not be valid, which must not be the case for any subclass of Mat2t<Float>

How may I overcome these problems?

Is there a way to have an abstract generic class Mat2t with a generic array and implement it with a subtype array?

1 Answer 1

4

You can accomplish this by making your generic parameter a subtype of Vec2t instead of a subtype of Vec2t's generic parameter type (T : Number):

abstract class Mat2t<T : Vec2t<*>>(open var value: List<T>)

class Mat2(override var value: List<Vec2>) : Mat2t<Vec2>(value)

Note that as you are overriding var value you don't need to have it in the abstract class constructor. The same applies for Vec2t. e.g.:

abstract class Vec2t<T : Number> {
    abstract var x: T
    abstract var y: T
}

class Vec2(override var x: Float, override var y: Float) : Vec2t<Float>()

abstract class Mat2t<T : Vec2t<*>> {
    abstract var value: List<T>
}

class Mat2(override var value: List<Vec2>) : Mat2t<Vec2>()

These abstract classes could then even be represented as interfaces instead if that suits you:

interface Vec2t<T : Number> {
    var x: T
    var y: T
}

data class Vec2(override var x: Float, override var y: Float) : Vec2t<Float>

interface Mat2t<T : Vec2t<*>> {
    var value: List<T>
}

data class Mat2(override var value: List<Vec2>) : Mat2t<Vec2>
Sign up to request clarification or add additional context in comments.

4 Comments

it works, nice. I see you used List over Array, is there a specific reason? To get covariance? For reference, I am trying to do a port of this. Cool tip about the interfaces, +1
@elect Habit I suppose. I almost never use Array. Plus I see your Vec2 is a data class which leads me to believe you might want Mat2 to be a data class as well in which case you would have to override equals and hashCode yourself if you used Array (it doesn't implement them) but with a List the compiler takes care of it for you. See also stackoverflow.com/q/36262305/3255152.
FYI: I'm not sure exactly what you are after but there are various linear algebra / matrix Java libraries out there: stackoverflow.com/questions/10815518/java-matrix-libraries. Maybe one of them already meets your use case; maybe not. Enjoy!
just a kotlin glm porting

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.