5

「ジェネリック」型を使用して方程式を計算するパッケージをGoで作成しようとしています。具体的には、ルンゲクッタ5近似を実装したいと思います。

この近似は、 atの値、開始時間、ステップ幅、および関数がどこにあるかという形式の微分方程式のみを使用yして、その点での(未知の)関数の値を計算します。t0 + hyt0t0hdgldy/dt = g(t,y)g

この近似は、スカラー型を操作する場合とベクトル(または行列)を操作する場合とまったく同じように動作します。より一般的に言えば、同じタイプの値に加算/減算でき、スカラー(私が使用しているfloat64)でスケーリングできるすべてのもので機能します

だから私はこれをGoインターフェースとして表現しようとしました:

type Numeric interface {
    Add(rhs Numeric) Numeric
    Sub(rhs Numeric) Numeric
    Mul(rhs float64) Numeric
}

しかし、このインターフェースを「実装」しようとすると、パラメーターのタイプが原因で問題が発生しました。

type Vec6F struct {
    x, y, z float64
    vx, vy, vz float64
}

func (lhs *Vec6F) Add(rhs *Vec6F) rk5.Numeric {
    result := new(Vec6F)
    result.x = lhs.x + rhs.x
    result.y = lhs.y + rhs.y
    result.z = lhs.z + rhs.z
    result.vx = lhs.vx + rhs.vx
    result.vy = lhs.vy + rhs.vy
    result.vz = lhs.vz + rhs.vz
    return result
}

これは私にエラーを与えます

cannot use result (type *Vec6F) as type rk5.Numeric in return argument:
        *Vec6F does not implement rk5.Numeric (wrong type for Add method
                have Add(*Vec6F) rk5.Numeric
                want Add(rk5.Numeric) rk5.Numeric

これは、一方では絶対に私にとって論理的です(rhsはNumericを実装する別のオブジェクトである可能性があるため)

しかし一方で、Goでそのようなことをどのように表現すればよいでしょうか。C ++では、代わりに演算子のオーバーロードを使用できましたが、それはgoでは不可能です。

4

3 に答える 3

2

ジェネリックであるためには、Addメソッドはパラメーターを取る必要がありNumericます。これに対処する通常の方法は、このようなタイプアサーションを使用することです(遊び場で

func (lhs *Vec6F) Add(_rhs Numeric) Numeric {
    result := new(Vec6F)
    rhs := _rhs.(*Vec6F) // type assertion - will panic if wrong type passes
    result.x = lhs.x + rhs.x
    result.y = lhs.y + rhs.y
    result.z = lhs.z + rhs.z
    result.vx = lhs.vx + rhs.vx
    result.vy = lhs.vy + rhs.vy
    result.vz = lhs.vz + rhs.vz
    return result
}

変換したいタイプが異なる場合は、タイプスイッチを使用することもできます。

于 2013-01-21T07:51:25.470 に答える
1

実際、ジェネリックは go ではサポートされていません。型にインターフェイスを実装する場合は、メソッドのプロトタイプが正確に一致する必要がありfunc (lhs *Vec6F) Add(rhs Numeric) Numericます。

以下は、型アサーションを使用してこのメ​​ソッドを記述しようとする試みです。

func (lhs *Vec6F) Add(rhs Numeric) Numeric {
    vrhs := rhs.(*Vec6F)
    result := new(Vec6F)
    result.x = lhs.x + vrhs.x
    result.y = lhs.y + vrhs.y
    result.z = lhs.z + vrhs.z
    result.vx = lhs.vx + vrhs.vx
    result.vy = lhs.vy + vrhs.vy
    result.vz = lhs.vz + vrhs.vz
    return result
}

適切なタイプの引数で呼び出された場合はコンパイルされ、機能するはずですが、それは乱用だと思います。

どちらも を実装するため、このメソッドを使用してベクトルをスカラーに追加することを妨げるものは何もありません (実行時エラーを除く) Numeric。結局、インターフェイスの抽象化を使用しても何も得られません。

この場合、go の哲学により、型固有のメソッド/関数の使用が指示されます。

于 2013-01-21T07:49:38.647 に答える
0

あなたが直面している2つの問題があります。

1.) コンパイルされず、インターフェイスが一致しないと不平を言う理由は、Vec6F が rk5.Numeric の関数シグネチャを満たしていないためです。戻り値と入力パラメーターの両方が型と一致する必要があります。

http://play.golang.org/p/kc9V9EXxJqはその問題を修正しますが、新しい問題を作成します...

2.) メソッド シグネチャを一致させて、Vec6F が Numeric のシグネチャを満たすようにするために、プロパティ値に対して数値演算を実行する機能が壊れていました。これは、インターフェイスにはメソッドのみがあり、プロパティがないためです。

あなたのユースケースでは、レシーバーが Add|Sub|Multi を実行する行列配列を返すアクセサー メソッドを Numeric インターフェイスが提供することは理にかなっていますか? これは、各インターフェイス実装のメソッド内で何を行う必要があるかを複雑にする可能性がありますが、探しているものが得られると思います.

于 2013-01-21T07:50:58.547 に答える