AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

"forward" von Units mit Record/Class Helpern

Ein Thema von Rollo62 · begonnen am 28. Aug 2018 · letzter Beitrag vom 28. Aug 2018
Antwort Antwort
Seite 1 von 2  1 2      
Rollo62

Registriert seit: 15. Mär 2007
4.116 Beiträge
 
Delphi 12 Athens
 
#1

"forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 08:50
Delphi-Version: 5
Hallo zusammen,

mangels besserer Bezeichnung nenne ich das was ich möchte mal "Unit forwarding",
und zwar aus einem Base-Unit die Klassen in ein Interface-Unit übernehmen und re-deklarieren.
So das nur noch das Interface-Unit in der Anwendung benutzt werden muss.


Base-Unit
Delphi-Quellcode:
interface Pages.Types;

type
    TPage_Elem = (Eins, Zwei); // Hier werden diese Klassen etc. definiert
    TPage_Elem_Helper = record helper for TPage_Elem; // Hier kann es Helper geben
       procedure DoDomething;
    end;

...
...
Interface-Unit
Delphi-Quellcode:
interface Pages;

Uses
    Pages.Types // Hier sind Klassen, Records, Enums, etc. definiert, s.o.
  ;

type
    TPage_Elem = Pages.Types.TPage_Elem; // Hier werden diese Klassen etc. ge-forwared
    TPage_Elem_Helper = Pages.Types.TPage_Elem_Helper; // das möchte ich auch mit Helpern so machen
und dann nur per Interface nutzen, während die Implementation in den Base-Units bleibt.

Delphi-Quellcode:
interface Main_Unit;

Uses
  Pages; // die Typen aus den Base-Units werden hier ge-forwarded und sind direkt nutzbar

...
...

procedure Test;
begin

  LElem := TPage_Elem.Eins; // Alles OK, kann ich benutzen mit Klassen, Records, Enums ...
  LElem.DoSomething // <-- ! Hier kann es nicht kompiliert werden, die Base-Units werden benötigt

end;

Gibt es da einen Trick wie man auch die Helper aus den Base-Units "forwarden" kann ?
Oder ist sowas etwa ein schlechter Stil ?

Rollo
  Mit Zitat antworten Zitat
Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 09:01
Spaßig dass es die Code Completion sogar vorschlägt, der Compiler aber dann aber nicht kann


Ich sehe den Gefallen nicht denn man sich mit diesem "Forwarding" tut. Um sich eine Zeile im uses zu sparen?
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.116 Beiträge
 
Delphi 12 Athens
 
#3

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 09:03
Bei viel Modularisierung ist es eben nicht nur eine Unit, sondern vielleicht auch 5.
Das macht sich schon bemerkbar
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 09:42
Wenn du so etwas schon machen willst und es dann auch noch Interface nennst, dann solltest du am besten auch mit Interfaces arbeiten

Dann sprichst du das Thema Modularisierung an. Da bietet es sich auch gleich im Zusammenhang mit Interfaces an, mit Factories zu arbeiten.

Schau dir das Thema mal an. Damit erreichst du eigentlich das was du willst und es wird noch modularer.

Edit:
Oh Moment ... du sprichst hier von Records
Naja vielleicht bringt es dir trotzdem was oder du kannst auf Klassen umstellen. (Die benutze ich zumindest lieber als Records)

Geändert von Aviator (28. Aug 2018 um 09:45 Uhr)
  Mit Zitat antworten Zitat
Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 10:53
Bei viel Modularisierung ist es eben nicht nur eine Unit, sondern vielleicht auch 5.
Das macht sich schon bemerkbar
Ich sehe trotzdem nicht dass das ein Vorteil ist. Damit versteckt man nur vor sich selber wovor die aktuelle Unit grade abhängig ist.


PS: Ich kann es schon etwas verstehen wenn man den Helper für ein Enum vermisst, darum geht es ja eigentlich. Entweder inkludierst du die Unit wo der Helper drinsteckt, oder du verabschiedest dich ganz vom Enum und nimmst stattdessen gleich einen Record der ein Enum kapselt. Deinem Record kannst du nun Methoden verpassen und brauchst keinen Helper mehr. Durch Operator-Überladung kannst du dein altes Enum diesem Record zuweisen und umgekehrt...


Delphi-Quellcode:
type
   TMyEnum = (uno, dos, tres);

   TMyEnumStruct = record
      Value: TMyEnum;
      function Next(): TMyEnumStruct;
      function Prev(): TMyEnumStruct;
      function ToString(): String;
      class operator Implicit(a: TMyEnumStruct): TMyEnum;
      class operator Implicit(a: TMyEnum): TMyEnumStruct;
   end;
und

Delphi-Quellcode:
procedure p();
var
   myEnum: TMyEnumStruct;
begin
   myEnum := TMyEnum.dos;
   myEnum := myEnum.Next();

   WriteLn( myEnum.ToString() );
end;
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.116 Beiträge
 
Delphi 12 Athens
 
#6

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 11:09
@Aviator
Ich nenne es Interface weil auch eins drin ist.
Die Helper sind Hilfs-Typen für das Interface.

@Günther
Mir ging es eigentlich im Wesentlichen um die Helper dabei.
Die funktionieren nämlich weder bei Enum noch den anderen Sprachelementen.

Ich möchte das Konzept so ja auch erstmal für mich einführen.
Ich nenne das für mich "API", in der Hoffnung das ich komplexere Dinge simpel in der Anwenung zusammenfassen kann.

Also z.B. Pages API die mir Alles für die Seitenverwaltung mitliefert, auch die Unterklassen, etc.
Es geht mir um eine einfache Lernkurve dabei, wo man eben nicht Alle 5 Unter-Units genau kennen muss.

Ich habe es bisher auch anders gelöst, und spiele gerade mit diesem Konzept etwas herum,
und bin nur verwundert das ausgerechnet die Helper sich nicht "forwarden" lassen,
der Rest der Elemente aber schon.
Liegts an mir, oder an ... ?

Rollo
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#7

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 11:34
und bin nur verwundert das ausgerechnet die Helper sich nicht "forwarden" lassen,
Das liegt an der Art wie Helper implementiert sind. Man kann das in etwa so betrachten wie globale Prozeduren und Funktionen.

Aus
Delphi-Quellcode:
type
    TPage_Elem_Helper = record helper for TPage_Elem
       procedure DoSomething;
    end;
wird dann intern so etwas in der Art
Delphi-Quellcode:

procedure TPage_Elem_Helper_DoSomething(var Self: TPage_Elem);
Damit der Compiler das auflösen kann, muss die Unit auch im uses erscheinen.

Es ist halt so, daß Helper nicht überall dort einsetzbar sind, wo andere Konstrukte funktionieren. Dies hier ist eben ein solcher Fall.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 11:52
Ich finde aber auch Helper sind ein Hilfsmittel, ein Notnagel oder ein bisschen Syntax-Zucker um Dinge lesbarer zu machen. Ein Helper ist, fast immer lokal auf die aktuelle Unit zugeschnitten.

Ich geb's ja zu, ich habe, genau wie du, auch oft Enums und direkt in der gleichen Unit gibt's noch den passenden Helper dazu, ob man will oder nicht.

Aber das ganze mit einem Record kapseln - Ist zwar ein bisschen mehr tippen, aber sonst in jeder Hinsicht besser, oder? Dann nimmst du deine Methoden (und sogar Variablen) auch gleich "mitgeforwardet" mit
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.116 Beiträge
 
Delphi 12 Athens
 
#9

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 14:01
Hallo Uwe,

ja dankesehr für die Erleuchtung, dann muss ich das Helper.forwarding wohl vergessen.


@Der schöne Günther,

Ok, das muss ich dann wohl so ähnlich machen.

Ich arbeite bevorzugt mit Enums, weil die sich im Gegensatz zu Konstanten "automatisch" richtig verhalten in den meisten Fällen, und super leicht erweiterbar sind.
Solche Enums ersetzen bei mir fast alle "Magic-Numbers".

Mit dem einbau in Records: Meinst du das Beste aus beiden Welten (enum/record-class) zu kombinieren ?
So in etwa:

Delphi-Quellcode:
type
  TTest_Record_Level2 = record
  public
  type
      TEnum = (COneHundret = 1, CTwoHundret, CThreeHundret);

  public
      class function OneHundret : TTest_Record_Level2.TEnum; {inline;} static; // inline needs Base unit
      class function TwoHundret : TTest_Record_Level2.TEnum; {inline;} static;
      class function ThreHundret : TTest_Record_Level2.TEnum; {inline;} static;

      class function ToInteger(const AEnum : TTest_Record_Level2.TEnum) : Integer; static;
  end;

...
...
...

class function TTest_Record_Level2.OneHundret: TTest_Record_Level2.TEnum;
begin
    Result := TTest_Record_Level2.TEnum.COneHundret;
end;

class function TTest_Record_Level2.ThreHundret: TTest_Record_Level2.TEnum;
begin
    Result := TTest_Record_Level2.TEnum.CTwoHundret;
end;


class function TTest_Record_Level2.TwoHundret: TTest_Record_Level2.TEnum;
begin
    Result := TTest_Record_Level2.TEnum.CThreeHundret;
end;

class function TTest_Record_Level2.ToInteger(const AEnum: TTest_Record_Level2.TEnum): Integer;
begin
    Result := Integer( AEnum ) * 100;
end;


...
...
...

procedure TForm1.Button5Click(Sender: TObject);
var
  LEnum : TTest_Record_Level2.TEnum;
  LInt: Integer;
begin

   LEnum := TTest_Record_Level2.OneHundret;
   LInt := TTest_Record_Level2.ToInteger( LEnum );
   if LEnum = TTest_Record_Level2.OneHundret then
   begin
       LEnum := TTest_Record_Level2.TwoHundret;
       LInt := TTest_Record_Level2.ToInteger( LEnum );
   end;

end;
Das funktioniert, kapselt die Enums, hat aber den Charme der simplen Helper etwas verloren
Kann man auch gleich class helper statt record helper nehmen, ist aber womöglich kein Unterschied.

Delphi-Quellcode:
      class function OneHundret : TTest_Record_Level2.TEnum; {inline;} static;
      class function TwoHundret : TTest_Record_Level2.TEnum; {inline;} static;
      class function ThreHundret : TTest_Record_Level2.TEnum; {inline;} static;
Wobei man die Funktionen auch weglassen, und direkt mit dem TEnum arbeiten kann.
Das mache ich z.T. bei einigen Klassen schon so.
Der Vorteil wäre wohl beim besseren AutoComplete, und das die Funktionen auch etwas mehr machen könnten als nur Werterückgabe.


      class function OneHundret : TTest_Record_Level2.TEnum; {inline;} static; // inline
Inline geht beim "forwarden" leider auch nicht, weil dann auch die Base-Units gebraucht werden (nicht zum Kompilieren, aber um 0 warnings zu Erreichen).


Stilfrage:
Da wäre dann noch die Frage zum Stil des "Unit-Forwarding".
Ich habe ja schon gehört das dies Einige nicht gut finden, ich sehe da nur ein Problem das man
"versteckte" Abhängigkeiten bekommt, im Gegensatz zu "offen sichtbaren" Abhängigkeiten in den uses.
Sonst sehe ich da keine anderen grundsätzlichen Probleme, oder gibt es die etwa doch ?

Rollo
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#10

AW: "forward" von Units mit Record/Class Helpern

  Alt 28. Aug 2018, 14:48
Ich habe ja schon gehört das dies Einige nicht gut finden, ich sehe da nur ein Problem das man
"versteckte" Abhängigkeiten bekommt, im Gegensatz zu "offen sichtbaren" Abhängigkeiten in den uses.
Die Basis-Unit wird doch in jedem Fall gebraucht, selbst wenn sie nicht explizit in der jeweiligen Uses-Anweisung drin steht.

Was verstehst du denn unter einer "versteckten" Abhängigkeit?
Ich verstehe darunter eigentlich genau das, was eben durch dieses "Typ-Forwarding" ausgelöst wird: Man nutzt ja schon die Basis-Unit, gibt sie aber nicht in der Uses-Anweisung an. Man ist also abhängig von der Basis-Unit, sieht es aber nicht gleich.

Die besagte inline-Warnung zeigt das ganz deutlich: Sie ist ja nicht nur eine Warnung, sondern der Compiler erzeugt dann auch anderen Code (nämlich non-inlined). Du bekommst also dasselbe wie ohne das inline. Der Compiler tut einfach so als wäre es nicht da.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:51 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz