![]() |
Maßeinheiten als Typen
Moinmoin,
da hier ![]() Dabei ist das ganze als Grundstock für ein größeres Bibleotheks-Projekt gedacht. Dabei gibts natürlich einige Anforderungen: 1. Die einzelnen Typen sollen sicher und eindeutig sein. Gemeint ist, das, wenn man das ganze als Parameter an eine Methode übergibt, keine andere Maßeinheit übergeben werden kann Beispiel:
Delphi-Quellcode:
Wenn versucht wird, hier Kilogram zu übergeben, soll der Compiler meckern.
Procedure TuWas(const a:gramm);
2. Rechenoperationen sollen möglich sein. D.h. Addition, Subtraktion, Division und Multiplikation 3. Vergleichsoperation sollen auch möglich sein. 4. Eine Möglichkeit, von einer Maßeinheit in eine andere Maßeinheit zu konvertieren/umzurechnen Wärend der Konzeptions und Tüftelphase (:)) bin ich auch auf das ein oder andere Problem gestoßen: a) Klassen funktionieren hier nicht Das größte Manko hier ist, das man keine Operatoren in Klassen definieren kann. Ein zweites, wenn auch weniger wichtiges Manko ist, das Klassen explizit erzeugt werden müssen. b) Records können nicht wirklich vererbt werden Ansonsten hätte man einen "Basistypen" geschaffen, und den Rest einfach davon abgeleitet, so das man das ganze mit weniger Aufwand umsetzen hätte können. c) Kein wirkliches forwarding bei Records Da man Records nur mit Zeigern forwarden kann, müssen einiges an Operatoren an ungewöhnlicher Stelle implementiert werden. D. h. dass zu Beispiel der Add-Operator für Gramm+Kilogram bei Kilogram implementiert wird, obwohl der Rückgabewert Gramm ist. Daher der Ansatz, für jede Maßeinheit einen entsprechenden Record schaffen. Wenn jemand einen alternativen Ansatz hat, immer her damit :) |
AW: Maßeinheiten als Typen
Dann erklär doch was die Problematik ist, wenn du ein Gewicht mit unterschiedlichen Einheiten übergibst.
Ich sehe da eigentlich kein Problem und bin daher der Meinung, dass ein Typ für Gewicht ausreicht und du keine Aufsplittung in Gramm, Kilogramm, Tonne Typen benötigst. |
AW: Maßeinheiten als Typen
Genaugenommen gibts 2:
1. Beispiel
Delphi-Quellcode:
das tut so nicht, da der Compiler meint es wären die gleichen Parameter.
Procedure Tuwas(const gramm:integer);overload;
Procedure Tuwas(const kilogram:integer);overload; 2. Beispiel
Delphi-Quellcode:
Hier könnte ich z.B. problemlos auch Tonnen übergeben, was u.U. zu recht...interresanten Problemen führen kann.
Procedure TuwasAnderes(const gramm:integer;const Kilogramm:integer);
Mit entsprechenden Typen kann ich sicherstellen, das dort, wo Gramm als Parameter erwartet wird, auch nur Gramm übergeben werden können. 3. Angenehmer Nebeneffekt
Delphi-Quellcode:
Würde ich hier z.B. einfach integer nehmen, könnte man das Ergebnis in die Tonne treten.
var
a : Gramm; b : Kilogramm; erg : Gramm; begin a := 10; b := 10; erg := a+b; //<-- Ergibt 10010 Gramm ! end; |
AW: Maßeinheiten als Typen
Das ist die Begründung dafür, warum du einen Typen für Gewicht benötigst, aber noch nicht die Begründung dafür, warum du mehrere Typen für Gewicht benötigst.
Delphi-Quellcode:
Und verwenden so
procedure Tuwas( const gewicht: TWeight );
begin ... end;
Delphi-Quellcode:
PS Als kleines Beispiel sei gennant, dass die Geschwindigkeit als Weg pro Zeit definiert ist und nicht als Meter pro Sekunde. Jede Geschwindigkeit kann auch als Meter pro Sekunde dargestellt werden und trotzdem gilt das auch wenn der Weg in Kilometer angegeben ist und die Zeit in Nanosekunden.
begin
Tuwas( TWeight.FromKilograms( 10 ) ); Tuwas( TWeight.FromGrams( 10 ) ); Tuwas( TWeight.FromTons( 10 ) ); end; |
AW: Maßeinheiten als Typen
und woher weis Tuwas, was er nun übergeben bekommen hat ? :)
Wenn die Methode nur mit bestimmte Einheiten arbeiten soll, hab ich hier nur die Möglichkeit, das über einen weiteren Parameter (nämlich die Einheit) und unterscheidet dann diese innerhalb der Methode. oder Es gibt für die entsprechenden Einheiten, entsprechende Überladungen. hmmmm... Natürlich könnte man in TWeight z.B. noch einen zusätzlichen wert für die Einheit mitführen. Aber letztlich würde das keine Vorteil bringen. Die Methoden und Operatoren müssten ja trotzdem die Einheiten unterscheiden. |
AW: Maßeinheiten als Typen
Zitat:
Das ergibt dann sowas wie
Delphi-Quellcode:
var
a:TWeight; b:TWeight; begin a.asKilogram = 10; b.asGramm = 10; TuWas(a+b); // 1010gramm werden übergeben end; |
AW: Maßeinheiten als Typen
Soweit schon richtig.
Und was machst du wenn Tuwas nur Gramm und Kilogramm verarbeiten soll nicht aber Tonnen oder Milligram ? Wie ich grad oben erweitert hab, kann Tuwas das ganze nicht unterscheiden. |
AW: Maßeinheiten als Typen
Hilft dir sowas?
Code:
Type
TKilogramm= type of Integer; TGramm = type of integer; ![]() |
AW: Maßeinheiten als Typen
Zitat:
Ich empfehle eine kurze Recherche bei Wikipedia zu Maßeinheiten, Vorsätzen und Einheitensystem zur Auffrischung. Möglich wäre auch, dass du dir mal anschaust wie das die Delphi RTL für System.TimeSpan.TTimeSpan regelt. Es ist mir beim Überfliegen dieses und des anderen Threads nicht ganz klar geworden, ob das mit den Gewicht nur ein Beispiel/Analogie ist oder du wirklich mit Gewichtsangaben arbeiten musst. Nehmen wir mal an, es geht wirklich um Gewicht, also du willst die physikalische Maßeinheit für die Masse in einer bestimmten Gravation beziffern: Gramm, Kilogramm, Tonne (1000 kg), Kilotonne (1000 * 1000 kg) sind keine verschiedenen Maßeinheiten. Es bezieht sich immer auf ein und dasselbe mit verschiedenen Vorsätzen für Maßeinheiten. Die SI-Basiseinheit für Masse ist das Kilogramm. Ein Gramm ist ein Tausendstel Kilogramm. Soweit bekannt, nix neues. Schaffe dir einfach einen einzigen konkreten Basisdatentyp, bspw. mit Gramm und gebe ihm die entsprechenden Methoden.
Delphi-Quellcode:
type
TKilogramm = type UInt64; TTonne = type UInt64; TKilogrammHelper = record helper for TKilogramm function ToString: string; end; TTonneHelper = record helper for TTonne function ToString: string; end; TGramm = type Double; TGewicht = record strict private FDasRichtigeGewichtInGrammAlsFliesskommazahl: TGramm; // Warum Fliesskomma? Vielleicht willst du auch mal Milli- und/oder Mikrogramm verarbeiten. // Man kann natürlich auch mit einen UInt32 oder UInt64 als Basis arbeiten, dann muss das aber im Vorfeld klar sein, welche die kleinste Größe ist. // Bei einen Kuchenrezept bspw. ist höchstwahrscheinlich die kleinste Gewichtsangabe sowas wie "eine Prise Salz/ein halbes Gramm". private // ggf. mit richtigen Gettern und Settern versehen property RawValue: TGramm read FDasRichtigeGewichtInGrammAlsFliesskommazahl write FDasRichtigeGewichtInGrammAlsFliesskommazahl; public class function Add(const A, B: TGewicht): TGewicht; static; function AsKilogramm: TKilogramm; // Hier kommen nur sinnvolle Werte größer null bei raus, wenn die interne Variable vor dem Komma mehr als 1000 groß ist. function AsTonne: TTonne; // Hier kommen nur sinnvolle Werte größer null bei raus, wenn die interne Variable vor dem Komma mehr als 1000 * 1000 groß ist. end; implementation { TGewicht } class function TGewicht.Add(const A, B: TGewicht): TGewicht; begin Result.RawValue := A.RawValue + B.RawValue; end; function TGewicht.AsKilogramm: TKilogramm; begin Result := Round(RawValue / 1000); end; function TGewicht.AsTonne: TTonne; begin Result := Round(RawValue / 1000 * 1000); end; { TKilogrammHelper } function TKilogrammHelper.ToString: string; begin end; { TTonneHelper } function TTonneHelper.ToString: string; begin end; |
AW: Maßeinheiten als Typen
Zitat:
:glaskugel: Aber du wirst deinen Grund haben. Interessieren würde es mich schon, weshalb z.B. nur "Tonnen" verwendet werden soll und alle anderen nicht. Gewicht ist Gewicht, egal welche Maßzahl verwendet wird. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz