我想建立一个
类的家庭根据帖子https://softwareengineering.stackexchange.com/q/325213/237600,我想出了这个:
public abstract class PrecisionSpace
{
protected static double TOL; // This value is supposed to be
// different in subclasses, so that...
public static bool TolEquals(double left, double right) // ... this method, ...
{
return (Math.Abs(left - right) <= TOL);
}
public static bool TolSmaller(double left, double right) // ... this method and ...
{
return (left + TOL < right);
}
public static bool TolLarger(double left, double right) // ... this method behave
// differently.
{
return TolSmaller(right, left);
}
}
然后我想定义子类
public class PerfectPrecision : PrecisionSpace
{
(new) private static double 0; // doesn't matter if I put "new" in front or not
}
public class MyPrecision: PrecisionSpace
{
(new) private static double 1E-10;
}
并且能够使用
之类的语句bool foo = MyPrecision.TolEquals(0, 1E-11); // supposed to be true
但它并不像我想要的那样工作,因为子类中的TOL
值未在PrecisionSpace
的静态方法中使用。因此无论我为T
放置哪个子类T.TolEquals(...)
,编译器总是使用超类PrecisionSpace
中定义的值(这是double
的默认值,即{{ 1}})。
简而言之,0
字段无法覆盖。那我该怎么办?
我可以删除所有static
修饰符,并在派生类的构造函数中设置所需的static
值。但后来我总是需要有类的实例。由于我不是真的需要实例,我可以让这些类单例化。但后来我必须确保它是线程安全的,等等......嗯。
还有什么?
我可以用与TOL
相同的方式编写不相关的类,使用静态方法,用PrecisionSpace
替换TOL
或0
或我为每个类选择的值。但这会产生大量冗余代码,并且由于这些类没有共同的基类或接口,我无法正确定义泛型,如下所示:
1E-10
还有其他想法吗?与代表们有什么关系吗?
对于那些提出问题&#34;为什么&#34;:请阅读我在问题开头链接的主题。
答案 0 :(得分:2)
继承不适用于静态成员。简而言之,你不能这样做。如果您想要多态行为,那么您将不得不创建实例。如果您的类构建为不可变的,那么线程安全应该不是问题。
public abstract class PrecisionSpace
{
private readonly double TOL;
protected PrecisionSpace(double tol) { TOL = tol; }
public bool TolEquals(double left, double right)
{
return (Math.Abs(left - right) <= TOL);
}
}
public sealed class PerfectPrecision : PrecisionSpace
{
public PerfectPrecision() : base(0) { }
}
internal static class PrecisionSpaceCache<T> where T : PrecisionSpace, new()
{
public static readonly T Instance = new T();
}
public class MyVector<T> where T : PrecisionSpace, new()
{
public void Foo(double x, double y)
{
PrecisionSpaceCache<T>.Instance.TolEquals(x, y);
}
}
这样您就可以在其他课程中使用PrecisionSpaceCache
(例如Matrix
)。另外,如果您打算创建很多类型,我会考虑将所有向量,矩阵等类转换为值类型(struct
)。
另一种选择是在Vector类的构造函数中传递精度。
答案 1 :(得分:0)
在基础.net框架中,你要做的最好的近似是Double,Int等系列,它们暴露相同的方法,但是对不同的数据类型进行操作并给出不同的结果。
如果功能相同(例如ToString),框架使用它调用的共享静态类来执行该功能。这减少了编码量,但没有使用继承等来减少端点数量。
答案 2 :(得分:0)
如果完全是语法上的便利而其他考虑并不重要,可以通过使用泛型类作为自己的参数来实现所需的效果,如下所示,允许您在静态方法中对其进行内部实例化,如下所示。
public class Precision<T> where T : Precision<T>, new()
{
protected virtual double TOL
{
get { throw new NotImplementedException(); }
}
public static bool TolEquals(double left, double right)
{
return (Math.Abs(left - right) <= new T().TOL);
}
}
在派生类中,您将覆盖虚方法。
public class PerfectPrecision : Precision<PerfectPrecision>
{
protected override double TOL
{
get { return 0.00f; }
}
}
public class MyPrecision : Precision<MyPrecision>
{
protected override double TOL
{
get { return 0.01f; }
}
}
这具有期望的效果,可以如下验证。
Console.WriteLine(PerfectPrecision.TolEquals(0.000f, 0.0001f));
Console.WriteLine(MyPrecision.TolEquals(0.000f, 0.0001f));
然而,这需要一些代价。能够从继承中受益的类实例的生成对于调用者来说是不可见的,但它们仍然发生。此外,类实际上并不是从相同的基类派生的,因为它们使用不同的类型参数。