3Pi*_*3Pi 7 c# inheritance abstract-class operator-overloading
我有一个抽象类Vector,我想重载运算符+, - ,*等.
我希望任何派生类能够使用它们,并获得一个与调用对象相同类型的对象.
我尝试使用泛型,(简称如下),但我找不到合法的方法:
public static T operator +<T>( T V1, T V2) where T : Vector
{
//some calculation
return new T(args);
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用基类来做到这一点:
public static Vector operator+(Vector V1, Vector V2)
{
if (V1.Dimension != V2.Dimension)
throw new VectorTypeException("Vector Dimensions Must Be Equal");
double[] ArgList = new double[V1.Dimension];
for (int i = 0; i < V1.Dimension; i++) { ArgList[i] = V1[i] + V2[i]; }
return (Vector)Activator.CreateInstance(V1.GetType(), new object[] { ArgList});
}
Run Code Online (Sandbox Code Playgroud)
如果此方法在两个子对象中传递,则它应对它们执行操作,并返回相同遗产的新对象.
我遇到的问题是我不能强制所有这样的子类必须有一个具有相应签名的构造函数,并且我不能调用基础构造函数来创建该对象.
有什么方法可以(a)使这些工作中的任何一个工作,或者(b)以另一种方式优雅地做到这一点?
Chr*_*air 11
您可以声明子类可以覆盖的实例级抽象方法:
public abstract class Vector
{
protected abstract Vector Add(Vector otherVector);
public static Vector operator +(Vector v1, Vector v2)
{
return v1.Add(v2);
}
}
public class SubVector : Vector
{
protected override Vector Add(Vector otherVector)
{
//do some SubVector addition
}
}
Run Code Online (Sandbox Code Playgroud)
可能遇到一些问题,特别是有多个子类(SubVector必须知道如何添加SomeOtherSubVectorClass?如果添加ThirdVectorType类?),或者可能处理null情况.此外,确保SubVector.Add行为与SomeOtherSubVectorClass.Add交换操作时的行为相同.
编辑:基于您的其他评论,你可以这样:
public class Vector2D : Vector
{
public double X { get; set; }
public double Y { get; set; }
protected override Vector Add(Vector otherVector)
{
Vector2D otherVector2D = otherVector as Vector2D;
if (otherVector2D != null)
return new Vector2D() { X = this.X + otherVector2D.X, Y = this.Y + otherVector2D.Y };
Vector3D otherVector3D = otherVector as Vector3D;
if (otherVector3D != null)
return new Vector3D() { X = this.X + otherVector3D.X, Y = this.Y + otherVector3D.Y, Z = otherVector3D.Z };
//handle other cases
}
}
public class Vector3D : Vector
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
protected override Vector Add(Vector otherVector)
{
Vector2D otherVector2D = otherVector as Vector2D;
if (otherVector2D != null)
return new Vector3D() { X = this.X + otherVector2D.X, Y = this.Y + otherVector2D.Y, Z = this.Z };
Vector3D otherVector3D = otherVector as Vector3D;
if (otherVector3D != null)
return new Vector3D() { X = this.X + otherVector3D.X, Y = this.Y + otherVector3D.Y, Z = this.Z + otherVector3D.Z };
//handle other cases
}
}
Run Code Online (Sandbox Code Playgroud)
EDITx2:
鉴于您的最新评论,也许您应该只维护一个内部数组/矩阵,只做通用矩阵数学.您的子类可以针对数组指示公开X/Y/Z属性包装器:
public class Vector
{
protected double[] Values;
public int Length { get { return Values.Length; } }
public static Vector operator +(Vector v1, Vector v2)
{
if (v1.Length != v2.Length)
{
throw new VectorTypeException("Vector Dimensions Must Be Equal");
}
else
{
//perform generic matrix addition/operation
double[] newValues = new double[v1.Length];
for (int i = 0; i < v1.Length; i++)
{
newValues[i] = v1.Values[i] + v2.Values[i];
}
//or use some factory/service to give you a Vector2D, Vector3D, or VectorND
return new Vector() { Values = newValues };
}
}
}
public class Vector2D : Vector
{
public double X
{
get { return Values[0]; }
set { Values[0] = value; }
}
public double Y
{
get { return Values[1]; }
set { Values[1] = value; }
}
}
public class Vector3D : Vector
{
public double X
{
get { return Values[0]; }
set { Values[0] = value; }
}
public double Y
{
get { return Values[1]; }
set { Values[1] = value; }
}
public double Z
{
get { return Values[2]; }
set { Values[2] = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
EDITx3:基于你的最新评论,我想你可以在每个子类上实现运算符重载,在静态方法中执行共享逻辑(比如在基类Vector类中),并在某处进行切换/大小写检查以提供特定的子类:
private static Vector Add(Vector v1, Vector v2)
{
if (v1.Length != v2.Length)
{
throw new VectorTypeException("Vector Dimensions Must Be Equal");
}
else
{
//perform generic matrix addition/operation
double[] newValues = new double[v1.Length];
for (int i = 0; i < v1.Length; i++)
{
newValues[i] = v1.Values[i] + v2.Values[i];
}
//or use some factory/service to give you a Vector2D, Vector3D, or VectorND
switch (newValues.Length)
{
case 1 :
return new Vector1D() { Values = newValues };
case 2 :
return new Vector2D() { Values = newValues };
case 3 :
return new Vector3D() { Values = newValues };
case 4 :
return new Vector4D() { Values = newValues };
//... and so on
default :
throw new DimensionOutOfRangeException("Do not support vectors greater than 10 dimensions");
//or you could just return the generic Vector which doesn't expose X,Y,Z values?
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后您的子类将具有:
public class Vector2D
{
public static Vector2D operator +(Vector2D v1, Vector2D v2)
{
return (Vector2D)Add(v1, v2);
}
}
public class Vector3D
{
public static Vector3D operator +(Vector3D v1, Vector3D v2)
{
return (Vector3D)Add(v1, v2);
}
}
Run Code Online (Sandbox Code Playgroud)
一些重复,但我没有看到一个方法绕过它顶部允许编译器执行此操作:
Vector3 v1 = new Vector3(2, 2, 2);
Vector3 v2 = new Vector3(1, 1, 1);
var v3 = v1 + v2; //Vector3(3, 3, 3);
Console.WriteLine(v3.X + ", " + v3.Y + ", " + v3.Z);
Run Code Online (Sandbox Code Playgroud)
或其他方面:
Vector2 v1 = new Vector2(2, 2);
Vector2 v2 = new Vector2(1, 1);
var v3 = v1 + v2; //Vector2(3, 3, 3);
Console.WriteLine(v3.X + ", " + v3.Y); // no "Z" property to output!
Run Code Online (Sandbox Code Playgroud)