2017-04-16 5 views
2

Ich versuche, die Duplizierung über einige Vektortypen zu reduzieren, indem Sie die Operatoren einmal definieren, aber ich bin mir nicht sicher, ob es möglich ist. Dies schien wie der vielversprechendste Ansatz:Kotlin: Konstrukt Wert von abgeleiteten generischen Typ in der Basisklasse

open class VecN<Derived: VecN<Derived>>(val buffer: FloatArray) { 
    operator fun minus(other: Derived) = Derived(buffer.zip(other.buffer, { a, b -> a - b }).toFloatArray()) 
    operator fun plus(other: Derived) = Derived(buffer.zip(other.buffer, { a, b -> a + b }).toFloatArray()) 
    ... many more operators... 
} 

class Vec2(x: Float, y: Float) : VecN<Vec2>(floatArrayOf(x, y)) 
class Vec3(x: Float, y: Float, z: Float) : VecN<Vec3>(floatArrayOf(x, y, z)) 
class Vec4(x: Float, y: Float, z: Float, w: Float) : VecN<Vec4>(floatArrayOf(x, y, z, w)) 

Das gibt mir „Typ Parameter Abgeleitete kann nicht als Funktion aufgerufen werden“, wo ich versuche, meine Abgeleitet Rückgabewert zu konstruieren.

Ist das in Kotlin möglich?

Antwort

3

Das geht nicht direkt, weil man in Kotlin nur einen Konstruktor eines konkreten Typs aufrufen kann, es gibt keine Möglichkeit, einen Konstruktor eines Typparameters aufzurufen. Darüber hinaus erlaubt Kotlin nicht, ein Array in eine Funktion/einen Konstruktor zu übergeben, der eine feste Anzahl separater Werte erwartet.

Sie können jedoch versuchen, dass die Verwendung einer abstrakten Funktion, ohne zu viel Textvorschlag zu erreichen, wie folgt aus:

abstract class VecN<Derived: VecN<Derived>>(val buffer: FloatArray) { 
    protected abstract fun createNew(buffer: FloatArray): Derived 

    operator fun minus(other: Derived) = 
     createNew(buffer.zip(other.buffer, Float::minus).toFloatArray()) 

    // ... 
} 

Dann müssen Sie in jedem der abgeleiteten Klassen diese Funktion außer Kraft setzen:

class Vec2(x: Float, y: Float) : VecN<Vec2>(floatArrayOf(x, y)) { 
    override protected fun createNew(buffer: FloatArray) = Vec2(buffer[0], buffer[1]) 
} 

(demo of this code)

+0

Danke: Das ist der Trick gemacht. Das 'Float :: minus' ist auch nett. (Das Fehlen eines Konstruktors, der ein Array verwendet, war eine Kopie/Paste-Kontrolle.) –

Verwandte Themen