我正在为我的学期项目开发一个单位转换器。我需要一些关于类/接口/抽象类结构的帮助。我想要一些可以被类(DegreesConverter、MassConverter、LenghtConverter)继承的接口或抽象类。像也许interface IUnitConvert<Type>
。对于初学者,我将处理角度单位(度、弧度、梯度)、力(牛顿、帕斯卡)和数据(字节、千字节、兆字节、千兆字节、太字节)。有什么建议么?
3 回答
首先想到的是有类似 System.TimeSpan 的东西,其中同一个类表示时间,您可以通过属性以不同的单位访问它。
您可以在内部将值存储在某个常量单位(可能是 SI)中,并将其转换为属性 getter/setter:
Distance d = new Distance;
d.Meters = 5000;
var km = d.Kilometers; // km = 5;
或者您可以为每个单元创建类:
public sealed class DistanceUnit
{
public DistanceUnit(string name, string symbol, double scale)
{
Name = name;
Symbol = symbol;
Scale = scale;
}
public string Name { get; private set; }
public string Symbol { get; private set; }
public double Scale { get; private set; }
}
public abstract class Distance
{
protected Distance(double value)
{
this.Value = value;
}
protected Distance()
{
}
public double Value { get; set; }
public abstract DistanceUnit Unit { get; }
public override string ToString()
{
return this.Value + " " + Unit.Symbol;
}
public static void Convert<TIn, TOut>(TIn original, out TOut result)
where TIn : Distance, new()
where TOut : Distance, new()
{
result = new TOut();
var scale = result.Unit.Scale / original.Unit.Scale;
result.Value = original.Value * scale;
}
}
public sealed class Meter : Distance
{
private static readonly DistanceUnit s_Unit = new DistanceUnit("Meter", "m", 1);
public Meter(double value) : base(value)
{
}
public Meter()
{
}
public override DistanceUnit Unit
{
get { return s_Unit; }
}
}
public sealed class Kilometer : Distance
{
private static readonly DistanceUnit s_Unit = new DistanceUnit("Kilometer", "km", .001);
public Kilometer()
{
}
public Kilometer(double value)
: base(value)
{
}
public override DistanceUnit Unit
{
get { return s_Unit; }
}
}
像这样使用
Meter distanceHome = new Meter(10000);
Kilometer distanceInKMs;
Distance.Convert(distanceHome, out distanceInKMs); // distanceInKMs.Value = 10
有很多不同的方法可以解决这个问题。这是使用委托的一种方式。
public class Converter
{
public static double Convert(double original, Func<double, double> conversion)
{
return conversion(original);
}
}
public class SizeConverter
{
public static double MegabytesToBytes(double megabytes)
{
return megabytes * 1048576;
}
public static double KilobytesToBytes(double kilobytes)
{
return kilobytes * 1024;
}
}
你会像这样使用它:
double result1 = Converter.Convert(2, SizeConverter.MegabytesToBytes);
double result2 = Converter.Convert(2, SizeConverter.KilobytesToBytes);
如果您需要双精度以外的其他类型,则需要重载 Convert 方法。
想想你想如何使用它,然后让它指导你。例如,您要表示哪种计量单位?你的基本单位是什么?计量单位之间的转换应该如何处理?
马上,我认为我们可以看到您将需要某种方式来表示测量单位,例如英尺、米、升、弗隆、度、千克、磅、居里、欧姆等。这似乎是一个类,或一系列类 - 可能以 Unit 为基础,以 Feet、Meters、Liters、Furlongs 作为子类。然后我认为你需要一些方法来将一个单元与一个值相关联。这个单位/值必须提供某种方法来在相同类型的测量单位(长度/距离、体积、温度、质量/重量)之间进行转换,并且如果调用代码尝试一些可疑的事情,则必须足够亮以引发合理的异常(例如将 27 摄氏度转换为英里/小时)。一些创建单位/值实例的便捷方法会很方便。单位/价值的东西不应该与特定种类或类别的单位联系在一起,
Codewise 我认为这样的事情会很棒:
UnitValue a, b, c;
a = new UnitValue(3 * 5280, Feet);
b = new UnitValue(180, Seconds);
c = (a / b).As(Miles / Hours);
cout << c;
应该希望打印类似的东西
60 miles/hour
所以你可以看到,将一个 UnitValue 除以另一个 UnitValue 应该产生一个具有复合单位的新 UnitValue - 在这种情况下,a / b
应该产生一个单位为英尺每秒(英尺/秒)的 UnitValue,As
然后转换例程将其转换为否则,在这种情况下每小时英里数。
我希望这有助于激发您的一些想法。
分享和享受。