2017-02-05 9 views
2

私はC#で継承を少し新しくしました。私は基底クラスVector.csを継承する2つのクラスVelocity.csPosition.csを持っています。私は、Velocity.csPosition.csからアクセス可能なVector.csの中にsubtract()というメソッドを作成しようとしています。C#継承の型キャストエラー

ここでは、減算のコードを示します。

 public Vector subtract(Vector v) { 
     double nx = this.x - v.x; 
     double ny = this.y - v.y; 
     double mag = Math.Sqrt(x * x + y * y); 
     double ang = Math.Atan2(y, x); 
     return new Vector(mag, ang); 
    } 

Velocity.csクラスを定義するコードは次のとおりです。

class Velocity : Vector{ 

    public Velocity(Position p1, Position p2, double vpref) : base(p1, p2) { 
     normalize(); 
     scale(vpref); 
    } 

    public Velocity(double vmax) : base(new Random().NextDouble()*vmax, new Random().NextDouble()*2*Math.PI) { 

    } 

    public void change(Velocity v) { 
     x = v.x; 
     y = v.y; 
     magnitude = Math.Sqrt(x * x + y * y); 
     angle = Math.Atan2(y, x); 
    } 

} 

}

私はこのような何か、外側の関数減算を呼び出そうとすると:

 Velocity v1 = new Velocity(5); 
     Velocity v2 = new Velocity(7); 
     Velocity result = v1.subtract(v2); 

私はが明示的に「速度」と「ベクトル」の間の変換はできませんというエラーを取得しますあなたはキャストを忘れましたか? タイプの未処理の例外「System.InvalidCastExceptionの」どのように私はこの仕事をするためにこの機能を書き換えることができ

を発生しました:

は、だから私は、次のエラーの結果があることがVelocity result = (Velocity)v1.subtract(v2);を試してみましたか?戻り値の型を持つ関数の3つのバージョンを実際に作成する必要がありますかVectorVelocityPosition?もしそうなら、継承のポイントは何ですか?私はそれらを関連するクラスに入れることができます。

注:ベロシティクラスはちょっと小さく、当時は無意味に思えるかもしれませんが、私はそれを後でさらに追加します。私はプロジェクトの途中です。

+1

サイドノート、ありません'新しいランダム()...、新しいランダム()...'を実行します。代わりに、Randomクラスの静的インスタンスを作成し、その代わりに使用します。それ以外の場合は、同じ番号を頻繁に使用します。 – pinkfloydx33

+0

また、subtractメソッドは 'Vector'を返します。それをタイプVelocityの変数に割り当てようとしています。 'Velocity'が' Vector'であることは事実ですが、 'Vector'は必ずしも' Velocity'( 'Position'でもよい)であるとは限りません。あなたはいつでも 'Vector result = v1.subtract(v2);'を実行することができますが、 'Vector'で定義されている共通フィールドにしかアクセスできません。もう一つの副作用:C#命名規則に従って、メソッド名は大文字、すなわち 'Change(...)'と 'Subtract(...)'で始めるべきです。 – pinkfloydx33

+0

最初の回答者のアプローチが気に入っています。 BTWは私を二重チェックします...私はそれがあなたがより簡単な方法で望むものと一致すると信じています。 –

答えて

1

ああ:Oあなたの目標を達成。したがって、減算関数はVectorオブジェクトを返しますが、C#はベクタをベロシティに戻すことはできません。私はコピーコンストラクタによってこれを取り上げる前にこれを打ちました。あなたのVelocityクラスで次に

public class Vector 
{ 
    /// <summary> 
    /// Copy Constructor 
    /// </summary> 
    /// <param name="toCopy"> 
    /// The vector object to copy 
    /// </param> 
    public Vector(Vector toCopy) 
    { 
     if (toCopy == null) 
     { 
      throw new ArgumentNullException("toCopy"); 
     } 

     x = toCopy.x; 
     y = toCopy.y; 
     //What ever other properties you have, assign them here 
    } 
} 

:あなたのVectorクラスでそう

最後に
public class Velocity : Vector 
{ 
    public Velocity(Vector vector) 
     : base(vector) 
    { 
    } 
} 

、これがどのように使用されるか:

Velocity result = new Velocity((v1).subtract(v2)); 
-2

あなたは3つのバージョンをコードするのに嫌うわけではありません。 汎用関数をコードすることができます。

public T Substract<T> (T vector) where T: Vector 
{ 
    ... 
    return new T(...); // Edited to demonstrate last line as asked from comment 
} 
+1

それは理にかなっていますが、最後の行はどのように見えますか? 'return new T(mag、ang);' – ryanmattscott

+0

これはとても良い答えです。 –

+0

@MatíasFidemraizer私はまだ何か間違っています..これは正しくない 'return T T:Vector、new(mag、ang);' – ryanmattscott

-1

あなたのコード

Velocity result = (Velocity)v1.subtract(v2); 

は速度型に減算方式の結果をキャストしないこと。ご了承くださいそれを行うための正しい方法は次のとおりです。

public class Vector<TImpl> where TImpl : Vector 
{ 
    public TImpl Subtract(TImpl v) 
    { 
     double nx = this.x - v.x; 
     double ny = this.y - v.y; 
     double mag = Math.Sqrt(x * x + y * y); 
     double ang = Math.Atan2(y, x); 

     return (TImpl)Activator.CreateInstance(typeof(TImpl), new object[] { mag, ang }); 
    } 
} 

public class Velocity : Vector<Velocity> 
{ 
} 

ところで、私はSubtractことを感じる:私はVectorクラスは、その派生クラスの種類を知っているようにジェネリック型パラメータを受け入れるべきであると信じてい

Velocity result = (Velocity)(v1.subtract(v2)); 
+0

いいえ、それはまったく同じことであり、彼/彼女の問題を解決しません。 –

+0

このコメントは間違っています。 '(T)v.s(u)'の形式の何かは、あなたが思っているように、 '((T)v).s(u)'ではなく、 '(T)(v.s(u))'余分な括弧はいいですが必須ではないので、あなたのコメントは間違っています。 –

2

この方法は、拡張メソッドである必要があり、すべてがそれほど奇妙に思えるだろう。

public static class VectorExtensions 
{ 
     public static TImpl Subtract<TImpl>(this TImpl vectorImpl, TImpl other) 
      where TImpl : Vector 
     { 
     double nx = this.x - v.x; 
     double ny = this.y - v.y; 
     double mag = Math.Sqrt(x * x + y * y); 
     double ang = Math.Atan2(y, x); 

     return (TImpl)Activator.CreateInstance(typeof(TImpl), new object[] { mag, ang }); 
     } 
} 

を...そしてあなたができるトンになるだろう私はここで何が起こっているか見

Velocity result = v1.Subtract(v2); 
+0

'(TImpl)Activator.CreateInstance(typeof(TImpl)、new object [] {m​​ag、ang})'を使用すると、醜いように見えます。 –

+0

@JeppeStigNielsen私に代わって、スニペットを改善します:D –

+0

@JeppeStigNielsenもう一つの方法は暗黙のインターフェイス実装を使って、パブリックにすることなくいくつかのプロパティを設定できるようにすることです... –