[Erledigt] Objektlisten erstellen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Objektlisten erstellen

Beitrag von Warf »

Wirklich? In den 15 Beiträgen hier hat noch niemand das Offensichtliche genannt? TFPGObjectList

Code: Alles auswählen

uses ..., fgl;
type
  TMyObjectList = specialize TFPGObjectList<TMyObject>;
 
var
  lst: TMyObjectList;
 
  lst := TMyObjectList.Create(true); // false falls die objekte nicht von der Liste gefreed werden sollen
  lst.Add(TMyObject.Create);
  lst[0].DoSomething;
  lst.Free;


Oder wenn man die Liste erweitern möchte:

Code: Alles auswählen

uses ..., fgl;
 
type
  TMyObjectList = class(specialize TFPGOBjectList<TMyObject>)
  ...
  end;
Zuletzt geändert von Warf am So 13. Jan 2019, 17:14, insgesamt 3-mal geändert.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Schreibe immer die Tabellennamen in Kleinbuchstaben, denn sollte es mal ein Linux-Server sein, dann geht das sonst nicht mehr.

Es ist ein Linux server und die tabelle heißt wirklich so.... darauf habe ich extra geachtet....

edit:
Wirklich? In den 15 Beiträgen hier hat noch niemand das Offensichtliche genannt? TFPGObjectList

So geht es natürlich auch, ich wollte doch eher bei der Pascal-standard Form bleiben...
MFG
Michael Springwald

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Bei mir bestehen auch schon immer alle Tabellennamen aus Groß- und Kleinschreibung. Weder unter Windows noch unter Linux gibt es damit Probleme.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Bei mir bestehen auch schon immer alle Tabellennamen aus Groß- und Kleinschreibung. Weder unter Windows noch unter Linux gibt es damit Probleme.

es ist schon richtig, man muss halt nur drauf achten.... da wird ja nicht auf Groß Kleinschreibung geachtet....
MFG
Michael Springwald

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Wenn ich das Füllen der Liste in der Klassenunit habe möchte, muß ich dann in der DB-Leseschleife jeweils die Objekte erstellen und mit den Daten füllen? Oder geht das nur außerhalb der Klasse?

Und noch eine Frage: was muss in der Liste zum hinzufuegen des Objekts in die .add-Prozedur?
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Und noch eine Frage: was muss in der Liste zum hinzufuegen des Objekts in die .add-Prozedur?

Wenn du mich meinst:
items.add(parameter)

mehr nicht... Früher habe ich das noch anders gelöst inzwischen mache ich es so...
MFG
Michael Springwald

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Objektlisten erstellen

Beitrag von Warf »

pluto hat geschrieben:So geht es natürlich auch, ich wollte doch eher bei der Pascal-standard Form bleiben...


Weil? Die Generische Klasse ist einfacher als die veraltete Version und sollte mindestens genauso guten wenn nicht sogar besseren Code erzeugen (da eine komplette Indirektionsebene wegfällt)
Das einzig doofe ist das Lazarus ein paar probleme hat wenn man nach "TFPGObjectList<" strg + Leer drückt. Ansonsten ist das ein Feature (was übrigens mittlerweile auch 10 Jahre alt ist, das Argument rückwärtskompatibilität lass ich also auch nicht gelten) was genau dafür entwickelt wurde das man eben nicht mehr so viel und so hässlichen Code schreiben muss und umso mehr, die chancen einen fehler bei einem einzeiler zu machen sind deutlich niedriger als bei einem 20 zeiler (oder wie groß dein Code ist).

Und in Pascal gibts genau zwei echte Standard Formen, ISO 7185 Pascal und ISO 10206 Extended Pascal. Ich hab beide mal ausprobiert, damit zu programmieren ist ein absoluter Graus (ist nicht mal OOP), da ist mir nicht standardkonformes FreePascal doch lieber. Oder was ist für dich die Pascal Standard form? Delphi 7? Turbo Pascal? FPC version 1.0? Mir kommt es so vor als hättest du die "Pascal-standard Form" recht willkürlich definiert.

An den Threadersteller, eventuell willst du sogar die SQL funktionalität direkt in die Liste integrieren:

Code: Alles auswählen

type
TMySQLObjectList = class(specialize TFPGObjectList<TMyObject>)
  function Add(Obj: TMyObject): Integer; override; // keine ahnung ob virtual, falls nicht lass das override weg
end;
 
function TMySQLObjectList.Add(Obj: TMyObject): Integer;
begin
  // SQL INSERT mit den Daten von TMyObject hier
  if SQLInsertWarErfolgreich then
    Result := inherited Add(Obj)
  else
  begin
    Result := -1;
    if FreeObjects then Obj.Free;
  end;
end;


Somit musst du in deinem letztendlichen Programmquelltext nur list.add(Obj) tippen und die Liste kümmert sich um das SQL. Somit ist garantiert das die Liste niemals nicht Synchron mit der Datenbank ist. Kommt aber natürlich auf dein Problem an, gibt genug fälle in denen man das nicht will

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Warf hat geschrieben:An den Threadersteller, eventuell willst du sogar die SQL funktionalität direkt in die Liste integrieren:

Code: Alles auswählen

type
TMySQLObjectList = class(specialize TFPGObjectList<TMyObject>)
  function Add(Obj: TMyObject): Integer; override; // keine ahnung ob virtual, falls nicht lass das override weg
end;
 
function TMySQLObjectList.Add(Obj: TMyObject): Integer;
begin
  // SQL INSERT mit den Daten von TMyObject hier
  if SQLInsertWarErfolgreich then
    Result := inherited Add(Obj)
  else
  begin
    Result := -1;
    if FreeObjects then Obj.Free;
  end;
end;


Somit musst du in deinem letztendlichen Programmquelltext nur list.add(Obj) tippen und die Liste kümmert sich um das SQL. Somit ist garantiert das die Liste niemals nicht Synchron mit der Datenbank ist. Kommt aber natürlich auf dein Problem an, gibt genug fälle in denen man das nicht will

Das ist annähernd das, was ich suche.

Ich möchte die Liste anhand einer Query mit allen gefundenen Sätzen füllen. Das ganze möglichst aus der Klassenunit.
Bisher ist mir dies nicht gelungen. Also im Prinzip der umgekehrte Weg.

Wenn ich das richtig interpretiere ist das obige der Weg, wenn ich im Pg, ein Obejkt erstellt und dieses dann an die DB gesendet habe
Zuletzt geändert von MacWomble am So 13. Jan 2019, 21:52, insgesamt 1-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Weil? Die Generische Klasse ist einfacher als die veraltete Version und sollte mindestens genauso guten wenn nicht sogar besseren Code erzeugen (da eine komplette Indirektionsebene wegfällt)
Das einzig doofe ist das Lazarus ein paar probleme hat wenn man nach "TFPGObjectList<" strg + Leer drückt.

Um Ehrlich zu, habe ich mir das noch nie genauer angesehen. Ich habe davon bisher nur gehört......
Lazarus hat sogar mit Manuell erzeugen Jsonen Code Probleme: In meinem Projekt erzeuge ich Jsonen code von "Hand" und zwischndurch kommt die IDE damit völlig durcheinander.
warum weiß ich nicht.

z.b. wenn ich dann stg+shift+Pfeiltaste Rauf oder Runter drücke, total Nervig...

was genau dafür entwickelt wurde das man eben nicht mehr so viel und so hässlichen Code schreiben muss und umso mehr, die chancen einen fehler bei einem einzeiler zu machen sind deutlich niedriger als bei einem 20 zeiler (oder wie groß dein Code ist).

Aber um jetzt bei diesem Beispiel zu bleiben: Die Syntax sagt mir einfach nicht zu. Dann kann ich ja gleich C bzw. C++ Programmieren.
Der Syntaxpraser hier im Forum hebt beim schlüsselword nicht mal "specialize" hervor...

Oder was ist für dich die Pascal Standard form? Delphi 7? Turbo Pascal? FPC version 1.0? Mir kommt es so vor als hättest du die "Pascal-standard Form" recht willkürlich definiert.

Ich hatte den Eindruck dass das erst vor wenigen Jahren in FPC eingeführt wurde, vielleicht habe ich mich auch getäuscht....
Ich habe mal gehört/gelesen das es kein definierten Pascal Standard gibt. So wie zum Beispiel Ansi C oder ähnlich.
(ich weiß damit widerspreche ich mich selbst...)

Somit musst du in deinem letztendlichen Programmquelltext nur list.add(Obj) tippen und die Liste kümmert sich um das SQL.

Was ich an diesem Code-Beispiel nicht verstehe, wie kommen da jetzt die Ergebnisse einer SQl-Abfrage rein?
Genau wie in meinem Code-Beispiel? Nur halt jetzt mit einer Generische Klasse?
MFG
Michael Springwald

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Objektlisten erstellen

Beitrag von Warf »

pluto hat geschrieben:Um Ehrlich zu, habe ich mir das noch nie genauer angesehen. Ich habe davon bisher nur gehört......
Lazarus hat sogar mit Manuell erzeugen Jsonen Code Probleme: In meinem Projekt erzeuge ich Jsonen code von "Hand" und zwischndurch kommt die IDE damit völlig durcheinander.
warum weiß ich nicht.

z.b. wenn ich dann stg+shift+Pfeiltaste Rauf oder Runter drücke, total Nervig...

Aber um jetzt bei diesem Beispiel zu bleiben: Die Syntax sagt mir einfach nicht zu. Dann kann ich ja gleich C bzw. C++ Programmieren.
Der Syntaxpraser hier im Forum hebt beim schlüsselword nicht mal "specialize" hervor...


es ist gewöhnungsbedürftig, aber sehr Praktisch, man hat sehr oft das Problem das man praktisch die selbe klasse für x verschiedene Typen braucht und dann immer zu kopieren und einzufügen und dann die Typen zu ersetzen braucht sehr viel zeit. C++ geht sogar noch weiter, da kann man konstanten über generics mitgeben, aber ich bin recht froh das Pascal einen zwingt einen neuen Typen mit Specialize zu initialisieren. In C++ ist das gang und gebe:

Code: Alles auswählen

std::vector<std::pair<std::string, std::vector<std::string>>>

oder sogar noch länger und die wenigsten entwickler definieren dafür dann einen eigenen typen. Das heißt bei jedem Konstruktor muss man dann den ganzen rattenschwanz schreiben:

Code: Alles auswählen

std::vector<std::pair<std::string, std::vector<std::string>>> vec;
vec.push_back(std::pair<std::string, std::vector<std::string>>("name", std::vector<std::string>())); // neues element hinzufügen

weshalb C++ eine neue form der Va Args eingeführt hat die man direkt an den Konstruktor übergeben kann:

Code: Alles auswählen

vec.emplace_back("name", std::vector<std::string>()); // neues element hinzufügen

Das ist mMn. komplett bescheuert. Die Pascal variante ist noch sehr zahm und auch recht einfach wenn man sich dran gewöhnt hat (und grade für Listen bietet es sich nunmal an)

Ich hatte den Eindruck dass das erst vor wenigen Jahren in FPC eingeführt wurde, vielleicht habe ich mich auch getäuscht....
Ich habe mal gehört/gelesen das es kein definierten Pascal Standard gibt. So wie zum Beispiel Ansi C oder ähnlich.
(ich weiß damit widerspreche ich mich selbst...)


Ich weiß nicht wann es in den FPC kam, in Delphi ists seit 2009, ich glaub das war ein paar jahre Später, aber wir haben es mindestens schon seit 6-8 Jahren

Was ich an diesem Code-Beispiel nicht verstehe, wie kommen da jetzt die Ergebnisse einer SQl-Abfrage rein?
Genau wie in meinem Code-Beispiel? Nur halt jetzt mit einer Generische Klasse?

Genau

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

He ihr Highjacker, bitte beim Thema bleiben - Danke :shock: :D

Ich versuche es mal anders. In meinem Formular möchte ich so etwas wie

Code: Alles auswählen

var
  ArtikelgruppenListe: TArtikelgruppenListel;
 
...
implementation
 
{$R *.frm}
 
function HoleArtikelgruppen : boolean;   
begin
    ArtikelgruppenListe := TArtikelgruppenListe.Create();
 
    ArtikelgruppenListe.ReadAllDataFromDB;   


Und dann sollte die ArtikelgruppenListe gefüllt sein. Keine DB-Geschichten im Formular.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

es ist gewöhnungsbedürftig, aber sehr Praktisch, man hat sehr oft das Problem das man praktisch die selbe klasse für x verschiedene Typen braucht und dann immer zu kopieren und einzufügen und dann die Typen zu ersetzen braucht sehr viel zeit.

Was heißt für dich sehr viel Zeit?
Ich brauche für eine neue Liste nach dem "Alten" Konzept ca 2 bis 4 Minuten ohne ersetzten und hinzufügen.
ich nutzte die Autovervollständigungen die Lazarus hier mit bringt.... dann ist es eine Sache von paar Minuten.

Das ist mMn. komplett bescheuert. Die Pascal variante ist noch sehr zahm und auch recht einfach wenn man sich dran gewöhnt hat (und grade für Listen bietet es sich nunmal an)

Da muss ich dir allerdings recht geben. Die Pacal Variante verstehe ich auf einen Blick, bei der C++ Variante müsste man schon genauer hinschauen.

Genau

Gut, also erstelle ich jetzt zum Beispiele eine Generische für einen bestimmten Zweck, nun muss ich nicht wieder eine neue erstellen für ein anderen Zweck?
Z.B. möchte ich in einer Liste Farben speichern und in andere anderen Liste Wörter.

He ihr Highjacker, bitte beim Thema bleiben - Danke

Ich muss sagen, wir sind recht lange beim Thema geblieben.... bis auf einen Ausrutscher würde ich sagen...

Und dann sollte die ArtikelgruppenListe gefüllt sein. Keine DB-Geschichten im Formular.

Gut, ich mache das mit einer nicht Grafischen Anwendung, ich denke aber es geht ganz ähnlich:

Code: Alles auswählen

ArtikelgruppenListe.ReadDataFromDB

In dieser Methode muss du dann diese Liste "Füllen", so wie ich es auch gemacht habe, egal ob du jetzt TObjectList verwendest oder die Generische Variante...
Wenn ich es richtig verstanden habe.

Ich versuche immer möglich vieles weg zu Kapseln.... wenn du so möchtest habe ich "Arbeiter" Klassen, die für mich z.b. sowas was du möchtest tun. Sie fragen die Datenbank ab und packen das Ergebnis in eine Liste. Es gibt "Anwender" Klassen, die das dann weiter verarbeiten. Z.B. um daraus Jsonen Code zu Erzeugen.
MFG
Michael Springwald

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Objektlisten erstellen

Beitrag von Warf »

MacWomble hat geschrieben:He ihr Highjacker, bitte beim Thema bleiben - Danke :shock: :D

Ich versuche es mal anders. In meinem Formular möchte ich so etwas wie

Code: Alles auswählen

var
  ArtikelgruppenListe: TArtikelgruppenListel;
 
...
implementation
 
{$R *.frm}
 
function HoleArtikelgruppen : boolean;   
begin
    ArtikelgruppenListe := TArtikelgruppenListe.Create();
 
    ArtikelgruppenListe.ReadAllDataFromDB;   


Und dann sollte die ArtikelgruppenListe gefüllt sein. Keine DB-Geschichten im Formular.


Dann würde ich alles in die TArtikelgruppenListe klasse packen, z.B.

Code: Alles auswählen

type
  TArtikelgruppenListe = class(specialize TFPGObjectList<TArtikelgruppe>)
  public
    constructor Create(DBInfo: TDBInfo); // übergibt die Datenbank informationen, die willst du womöglich aus einer Config datei lesen oder so
    procedure LoadDataFromDB(); // Lädt daten von der DB
    function Add(Obj: TArtikelGruppe): Integer; // Fügt element zur liste (inherited add) hinzu und zur Datenbank
    procedure Delete(Index: Integer); // Löscht aus der Daten aus der Liste (inherited Delete) und aus der Datenbank
    ...
  end;


Du kannst den SQL code auch in der TArtikelgruppe haben, das macht mehr sinn wenn du die daten auch außerhalb der Liste Managen willst. Wenn die liste aber sozusagen der Owner der daten ist (also die daten nur im rahmen der Liste hinzugefügt oder gelöscht werden), würde ich die sich auch um den SQL kram kümmern lassen. Änderungen an den Daten selbst musst du eh in der TArtikelGruppe machen.

Eine dritte Option ist die Verwendung von Events, du kannst eine Separate klasse bauen die sich um den SQL kram kümmert, und jedes Objekt sowie die liste haben dann Events wie OnChange (ArtikelGruppe) OnAdd(Liste) OnDelete (Liste), etc.

Was davon das beste ist kann ich dir nicht sagen, das mit den Events ist wohl am flexibelsten, aber auch am undurchsichtigsten was wann wo passiert

Gut, also erstelle ich jetzt zum Beispiele eine Generische für einen bestimmten Zweck, nun muss ich nicht wieder eine neue erstellen für ein anderen Zweck?
Z.B. möchte ich in einer Liste Farben speichern und in andere anderen Liste Wörter.


Ich finde das kann man sich recht einfach vorstellen, wenn irgendwo specialize TGenerischeKlasse<Typ> steht, kopiert der kompilier sozusagen die gesammte generische Definition der Liste und ersetzt jedes Vorkommen mit dem Generischen Parameter mit dem Typen. Es ist also praktisch genau das was du expliziet per hand machst, nur automatisiert vom kompiler. Und im gegensatz zu C++ passiert bei Pascal da nicht sonderlich viel Compiler magic, es ist also eigentlich wirklich nur eine Abkürzung für den alten weg. Bei C++ wirds ganz verrückt, da versucht der Kompiler automatisch die Typen zu erkennen, man kann also templates (so heißt das in C++) verwenden ohne es zu merken (mal ganz davon abgesehen das C++ noch viel viel mehr mit den templates kann, so viel das ich nach 2 Jahren C++ immer wieder von templates überrascht werde).

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Zum Highjacking:
Ist schon klar, ich bin ja froh, dass ihr mir helft! Auch sind die Informationen recht interessant. Nur dachte ich, man sollte das hier nicht in die falsche Richtung laufen lassen.
War nicht böse gemeint!

Warf hat geschrieben:Du kannst den SQL code auch in der TArtikelgruppe haben, das macht mehr sinn wenn du die daten auch außerhalb der Liste Managen willst. Wenn die liste aber sozusagen der Owner der daten ist (also die daten nur im rahmen der Liste hinzugefügt oder gelöscht werden), würde ich die sich auch um den SQL kram kümmern lassen. Änderungen an den Daten selbst musst du eh in der TArtikelGruppe machen.


Soweit ist das schon klar. Neine, es ist schon OK, in der TArtikelgruppenliste diesen Code zu haben. Ich verstehe dennoch noch nicht richtig, wie ich das Objekt Artikelgruppe in der Function ReadAllDataFromDB der TArtikelgruppenliste verwende.

Aber ich bin noch am testen ... und glaube so langsam auf dem Weg zu sein. Bei Bedarf melde ich mich wieder. :oops:
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Soweit ist das schon klar. Neine, es ist schon OK, in der TArtikelgruppenliste diesen Code zu haben. Ich verstehe dennoch noch nicht richtig, wie ich das Objekt Artikelgruppe in der Function ReadAllDataFromDB der TArtikelgruppenliste verwende.

schau dir doch mal meine Funktion im ersten Post an, wo du mich auf das Open hingewiesen hast. statt Items.add(..) musst du halt was anders schreiben
(ich glaube mehr ist das nicht)
MFG
Michael Springwald

Antworten