2017-04-16 19 views
2

演算子を一度定義することによっていくつかのベクトル型間で重複を減らそうとしていますが、それは可能ではないかと思います。これは、最も有望なアプローチのように見えた:Kotlin:基本クラスの派生ジェネリック型の値を構築する

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)) 

これは私が私の派生戻り値を構築しようとする「派生型のパラメータを関数として呼び出すことはできません」私を与えます。

これはKotlinで可能ですか?

答えて

3

Kotlinでは、具体的な型のコンストラクタしか呼び出せないため、型パラメータのコンストラクタを呼び出す方法がないため、簡単にはできません。さらに、Kotlinは、固定数の別個の値を必要とする関数/コンストラクタに配列を渡すことを許可しません。

しかし、あなたはこのように、あまりにも多くの決まり文句なしに抽象機能を使用していることを達成しようとすることができます:

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()) 

    // ... 
} 

次にあなたが派生クラスのそれぞれに、この関数をオーバーライドする必要があります。

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

ありがとうございました:これはトリックです。 'Float :: minus'も素晴らしいです。 (配列を取るコンストラクタの欠如は、コピー/ペーストの監視でした。) –

関連する問題