2010-01-06 6 views
1

Je développe un convertisseur d'unité pour mon projet de semestre. J'ai besoin d'aide sur la structure des classes/interfaces/classes abstraites. Je veux une interface ou une classe abstraite qui peut être héritée par les classes (DegreesConverter, MassConverter, LenghtConverter). Comme peut-être interface IUnitConvert<Type>. Je traiterai des unités d'angles (degrés, radians, grades), de force (newtons, pascals) et de données (octets, kilooctets, mégaoctets, gigaoctets, téraoctets) pour les débutants. Aucune suggestion?Programme de convertisseur d'unité

+0

Qu'est-ce que vous avez jusqu'à présent? – John

+0

Désolé, rien que l'interface utilisateur. –

Répondre

2

La première qui vient à l'esprit est d'avoir quelque chose comme System.TimeSpan où la même classe représente le temps et vous y accéder à différentes unités via les propriétés.

Vous stocker la valeur interne dans une unité constante (probablement SI) et le convertir dans le getter/setter propriété:

Distance d = new Distance; 
d.Meters = 5000; 
var km = d.Kilometers; // km = 5; 

Vous pouvez également créer des classes pour chaque unité:

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

qui est utilisé comme

Meter distanceHome = new Meter(10000); 
Kilometer distanceInKMs; 

Distance.Convert(distanceHome, out distanceInKMs); // distanceInKMs.Value = 10 
+0

Est-ce que j'utiliserais la même méthode Distance.Convert? –

+0

Oui, il en serait de même pour deux implémentations de Distance (Meter, Feet Mile, etc), que vous lui passez. –

0

Il y a beaucoup de façons différentes que vous pouvez aborder ce sujet. Voici une façon d'utiliser les délégués.

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

Vous souhaitez utiliser cela comme ceci:

 double result1 = Converter.Convert(2, SizeConverter.MegabytesToBytes); 
     double result2 = Converter.Convert(2, SizeConverter.KilobytesToBytes); 

Si vous avez besoin d'autres types autres que doubler, vous aurez besoin de surcharger la méthode Convert.

+0

Seul problème avec cette approche est que vous obtenez une explosion combinatoire dans l'énumération SizeConverter que vous ajoutez plus d'unités - BytesToKB? MBtoKB? Que se passe-t-il une fois que j'ajoute des gigaoctets? – Paolo

+0

En utilisant b/kb/mb/gb/tb il y aura 20 méthodes pour toutes les conversions possibles, non? Je ne pense pas que ce soit déraisonnable, étant donné que chaque conversion est essentiellement 1 ligne de code. – mdm20

+0

Vous avez raison Je ne pense pas que ce soit quelque chose dont vous auriez à vous soucier dans le cadre d'un projet de classe. – slimbo

0

Pensez à comment vous voulez utiliser, et laisser ce guide vous. Par exemple, quels types d'unités de mesure voulez-vous représenter? Quelles seront vos unités de base? Comment les conversions entre unités de mesure doivent-elles être traitées?

Juste à côté, je pense que nous pouvons voir que vous allez avoir besoin d'une certaine façon de représenter une unité de mesure, par exemple pieds, mètres, litres, furlongs, degrés, kilogrammes, livres, curies, ohms, etc. Cela semble être une classe, ou une série de classes - peut-être l'unité comme base, avec pieds, mètres, litres, furlongs comme sous-classes. Ensuite, je pense que vous aurez besoin d'un moyen d'associer une unité à une valeur. Cette unité/valeur devra fournir un moyen de convertir entre unités de mesure du même type (longueur/distance, volume, température, masse/poids) et être assez brillante pour émettre une exception raisonnable si le code appelant tente quelque chose de louche (comme la conversion de 27 degrés Celsius en miles/heure). Un moyen pratique de créer des instances unité/valeur serait pratique. L'unité/la valeur ne devrait pas être liée à un type ou à une classe particulière d'unité, mais devrait heureusement être capable de gérer n'importe quelle unité que vous voulez lui lancer.

Codewise Je pense que quelque chose comme ça serait génial:

UnitValue a, b, c; 

a = new UnitValue(3 * 5280, Feet); 
b = new UnitValue(180, Seconds); 
c = (a/b).As(Miles/Hours); 
cout << c; 

devrait, espérons imprimer quelque chose comme

60 miles/hour 

vous pouvez donc voir que la division d'un UnitValue par un autre UnitValue devrait produire une nouvelle UnitValue avec une unité composée - dans ce cas, le a/b devrait produire un UnitValue avec des unités de pieds par seconde (pieds/secondes), la routine As conversion convertit alors quelque chose d'autre, dans ce cas miles par heure. J'espère que cela contribuera à susciter un peu de réflexion de votre part.

Partagez et appréciez.