Delphi-PRAXiS
Seite 1 von 8  1 23     Letzte » 

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Maßeinheiten als Typen (https://www.delphipraxis.net/198184-masseinheiten-als-typen.html)

Ghostwalker 11. Okt 2018 06:54

Maßeinheiten als Typen
 
Moinmoin,

da hier Unittests generieren die Frage aufgekommen ist, ob das Konzept, das als eigene Typen zu implementieren, stell ich hier mal die Frage nach Alternativen (schließlich kann auch ein SE mal irren).

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:
   Procedure TuWas(const a:gramm);
Wenn versucht wird, hier Kilogram zu übergeben, soll der Compiler meckern.

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

Schokohase 11. Okt 2018 07:09

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.

Ghostwalker 11. Okt 2018 07:46

AW: Maßeinheiten als Typen
 
Genaugenommen gibts 2:

1. Beispiel

Delphi-Quellcode:
Procedure Tuwas(const gramm:integer);overload;
Procedure Tuwas(const kilogram:integer);overload;
das tut so nicht, da der Compiler meint es wären die gleichen Parameter.

2. Beispiel

Delphi-Quellcode:
Procedure TuwasAnderes(const gramm:integer;const Kilogramm:integer);
Hier könnte ich z.B. problemlos auch Tonnen übergeben, was u.U. zu recht...interresanten Problemen führen kann.
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:
var
  a : Gramm;
  b : Kilogramm;
  erg : Gramm;

begin
  a := 10;
  b := 10;
  erg := a+b; //<-- Ergibt 10010 Gramm !
end;
Würde ich hier z.B. einfach integer nehmen, könnte man das Ergebnis in die Tonne treten.

Schokohase 11. Okt 2018 07:54

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:
procedure Tuwas( const gewicht: TWeight );
begin
  ...
end;
Und verwenden so
Delphi-Quellcode:
begin
  Tuwas( TWeight.FromKilograms( 10 ) );
  Tuwas( TWeight.FromGrams( 10 ) );
  Tuwas( TWeight.FromTons( 10 ) );
end;
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.

Ghostwalker 11. Okt 2018 08:11

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.

bernau 11. Okt 2018 08:22

AW: Maßeinheiten als Typen
 
Zitat:

Zitat von Ghostwalker (Beitrag 1415473)
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.

"TuWas" wurde TWeight übergeben. Mehr muss "Tuwas" nicht wissen. TWeight ist ein Record welches ein Value mit der Einheit (z.B. "Gramm") besitzt. Über die Funktionen "FromKilograms( 10 )" wird automatisch in Gramm umgerechnet. So mache ich das auch seit einiger Zeit, seit ich Operatoren in Records kennen gelernt habe. Ich mache daraus noch ein "Property asKilogram" somit kann man in beide Richtungen arbeiten.

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;

Ghostwalker 11. Okt 2018 08:26

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.

TigerLilly 11. Okt 2018 08:31

AW: Maßeinheiten als Typen
 
Hilft dir sowas?

Code:
Type
  TKilogramm= type of Integer;
  TGramm = type of integer;
http://docwiki.embarcadero.com/RADSt...%A4t_von_Typen

TiGü 11. Okt 2018 08:36

AW: Maßeinheiten als Typen
 
Zitat:

Zitat von Ghostwalker (Beitrag 1415460)
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:
   Procedure TuWas(const a:gramm);
Wenn versucht wird, hier Kilogram zu übergeben, soll der Compiler meckern.

Vorweg:
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;

bernau 11. Okt 2018 08:38

AW: Maßeinheiten als Typen
 
Zitat:

Zitat von Ghostwalker (Beitrag 1415477)
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.

"TuWas" muss es ja auch nicht unterscheiden. "TuWas" erhält immer nur den Wert "TWeight".

: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 21:22 Uhr.
Seite 1 von 8  1 23     Letzte » 

Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf