Программа конвертации единиц - PullRequest
1 голос
/ 07 января 2010

Я разрабатываю конвертер для своего семестрового проекта. Мне нужна помощь по структуре классов / интерфейсов / абстрактных классов. Я хочу некоторый интерфейс или абстрактный класс, который может быть унаследован классами (DegreesConverter, MassConverter, LenghtConverter). Как может быть interface IUnitConvert<Type>. Я буду иметь дело с единицами углов (градусы, радианы, градианы), силой (ньютоны, паскали) и данными (байт, килобайт, мегабайт, гигабайт, терабайт) для начинающих. Есть предложения?

Ответы [ 3 ]

2 голосов
/ 07 января 2010

Первое, что приходит на ум, - это иметь что-то вроде 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
1 голос
/ 07 января 2010

Есть много разных способов подойти к этому. Вот один из способов использования делегатов.

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);

Если вам нужны другие типы, кроме double, вам необходимо перегрузить метод Convert.

0 голосов
/ 07 января 2010

Подумайте, как бы вы хотели использовать это, и пусть это направляет вас.Например, какие единицы измерения вы хотите представить?Какими будут ваши базовые подразделения?Как следует обрабатывать преобразования между единицами измерения?

Сразу я думаю, мы можем видеть, что вам понадобится какой-то способ представления единицы измерения, например, футы, метры, литра, фарлонги, градусы,килограммы, фунты, кюри, омы и т. д. Это, кажется, класс или серия классов - возможно, Unit в качестве основы, с футами, метрами, литрами, Furlongs в качестве подклассов.Тогда я думаю, что вам нужен какой-то способ связать единицу со значением.Эта единица / значение должна обеспечивать какой-либо способ преобразования единиц измерения одного типа (длина / расстояние, объем, температура, масса / вес) и быть достаточно ярким, чтобы вызвать разумное исключение, если вызывающий код пытается что-то подозрительно (например, преобразование 27 градусов по Цельсию в мили / час).Будет удобен некоторый удобный способ создания экземпляров единиц / значений.Единица единицы / значения не должна быть привязана к определенному виду или классу единиц, но, к счастью, должна быть в состоянии справиться с любой единицей, которую ты хочешь бросить в нее.быть великим:

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 в другое значение, в данном случае миль в час.

Я надеюсь, что этопомогает вам задуматься.

Делитесь и наслаждайтесь.

...