Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Zugriff auf Objekt in Klasse (https://www.delphipraxis.net/206473-zugriff-auf-objekt-klasse.html)

FediDelPr 25. Dez 2020 16:12

Zugriff auf Objekt in Klasse
 
Im Umgang mit Klassen (eigene Definitionen) bin ich noch nicht wirklich geübt.

Jetzt bin ich aber doch einigermassen erstaunt darüber, dass der Compiler folgendes
frisst:

Ich definiere eine eigene Klasse:

Code:
  TEmailCoreObject = CLASS(TObject)
    IMAPClient: TIdIMAP4;
    ...
und greife dann darauf zu, ohne vorher eine Instanz gebildet zu haben.
Code:
    IMAPClient.Host := 'imaps.gmail.com';
    IMAPClient.Port := 993;
Warum geht das ?
Macht das Sinn ?

Mit einer Typendeklaration RECORD ... geht das nicht, ich muss zuerst eine
Variable mit diesem Typ definieren.

Habe ich etwas nicht kapiert ?

FediDelPr 25. Dez 2020 16:25

AW: Zugriff auf Objekt in Klasse
 
Der Fall liegt vermutlich etwas komplizierter. Studiert im Moment noch
nicht zuviel daran herum.
Ich werde ein Präzisierung nachliefern.

haentschman 26. Dez 2020 05:29

AW: Zugriff auf Objekt in Klasse
 
Moin...8-)
Zitat:

dass der Compiler folgendes frisst ... Warum geht das ?
...und zur Laufzeit macht es Bummm! :zwinker:

Delphi-Quellcode:
TEmailCoreObject = CLASS(TObject)
  IMAPClient: TIdIMAP4;
...Felder einer Klasse werden immer mit F gekennzeichnet. Da liegt u.a. an einer Property...wenn man es braucht. :zwinker:
StyleGuide:
https://www.delphi-treff.de/object-pascal/styleguide/
Bitte denke auch ggf. an die Sichtbarkeiten...wenn benötigt.
http://docwiki.embarcadero.com/RADSt...assenelementen

Besser:
Delphi-Quellcode:
TEmailCoreObject = class
private
 
protected
  FIMAPClient: TIdIMAP4; // protected...weil das auch in der abgeleiteten Klasse nach Core verfügbar sein soll, oder?
public
  constuctor Create;
  destructor Destroy; override;
  property IMAPClient: TIdIMAP4 read FIMAPClient write FIMAPClient; // ggf. als property nach "Außen"
end;

...

constructor TEmailCoreObject.Create;
begin
  FIMAPClient := TIdIMAP4.Create;
end;

destructor TEmailCoreObject.Destroy;
begin
  FIMAPClient.Free;
  inherited;
end;

FediDelPr 26. Dez 2020 19:57

AW: Zugriff auf Objekt in Klasse
 
@Haentschman
danke, werde das genauer ansehen.

Ich hab's jetzt nochmals genauer angeschaut:

Eine Instanz von IMAPClient oder neu jetzt FIMAPClient wurde erzeugt und
das überrascht mich jetzt, ohne vorher eine Instanz von TEmailCoreObject
gebildet zu haben. Es existiert also nur:

Code:
TEmailCoreObject = CLASS(TObject)
   ...
 PUBLIC
   FIMAPClient: TIdIMAP4;
END;
und eine uninitialisierte Instanz von TEmailCoreObject in einem übergeordneten Modul
(ohne je ein Create durchgeführt zu haben). Und es läuft trotzdem.

Nebenbei:
Sehe ich das richtig, dass FIMAPClient ohne Schlüsselwort mit PUBLIC gleichzusetzen
ist? Mindestens so scheint es bei mir zu funktionieren.

himitsu 26. Dez 2020 20:55

AW: Zugriff auf Objekt in Klasse
 
Der Name ist vollkommen egal.

Und egal ob Record oder Class, die Instanz von TIdIMAP4 mußt du immer erstllen.
Es wird da garnichts automatisch gemacht.

Beim Class muß natürlich auch noch die Instanz von TEmailCoreObject erstellt werden.


Einziger Unterschied, das Feld (FIMAPClient) wird in der Klasse automatisch mit NIL initialisiert.
Ob das auch bei dem Record passiert, hängt davon ab, wo diese Variable liegt. (lokale Variablen in Prozeruden/Methoden sind nie initialisiert)

haentschman 27. Dez 2020 05:42

AW: Zugriff auf Objekt in Klasse
 
Moin...:P
Zitat:

das überrascht mich jetzt, ohne vorher eine Instanz von TEmailCoreObject
Du darfst aber die Komponente nicht auf die Form ziehen...Weil das riecht danach. :zwinker:
Zitat:

Sehe ich das richtig, dass FIMAPClient ohne Schlüsselwort mit PUBLIC gleichzusetzen
Prinzipiell ja. Aber...ich würde das den Compiler nicht selbst entscheiden lassen...ich entscheide wer was ist! :thumb: Später heraus willst du vieleicht Felder hinzufügen, die nicht Properties sind...dann greift die Sichtbarkeit (public, private, protected). :wink: Also, warum nicht gleich so? :zwinker:

himitsu 27. Dez 2020 14:18

AW: Zugriff auf Objekt in Klasse
 
Zitat:

Sehe ich das richtig, dass FIMAPClient ohne Schlüsselwort mit PUBLIC gleichzusetzen
Ja
und auch NEIN.

Normalerweise ist bei Objekten und auch Records der Default das "public".

ABER alles ab TComponent TPersistent, da ist es "published", da {$M+} !
http://docwiki.embarcadero.com/RADSt...tionen_(Delphi)
Darum sind die Komponenten-Variablen in TForms am Anfang eben auch published, damit der DFM-Reader diese Varialen und die EventMethoden finden kann.

TurboMagic 28. Dez 2020 15:56

AW: Zugriff auf Objekt in Klasse
 
Zitat:

Zitat von FediDelPr (Beitrag 1479889)
Nebenbei:
Sehe ich das richtig, dass FIMAPClient ohne Schlüsselwort mit PUBLIC gleichzusetzen
ist? Mindestens so scheint es bei mir zu funktionieren.

Ja. Das sollte man selber aber besser vermeiden, da es nicht im Sinne der OOP ist.
Nur VCL/FMX Klassen brauchen dieses Verhalten, da alle in dieser "nicht" Sektion
deklarierte Felder die auf der Form liegenden Komponenten sind, deren eigentliche
Erzeugung/Initialisierung über den Form Streaming Mechanismus erfolgt.

Aber du solltest dir's besser gleich abgewöhnen.

FediDelPr 3. Jan 2021 23:05

AW: Zugriff auf Objekt in Klasse
 
Ich bin da weiterhin am Üben.

Die Klassendefinition habe ich geändert, so dass nun TEmailCoreObject ein
Nachkomme von TidIMAP4 ist.

Code:
TYPE
  TEmailCoreObject = CLASS(TidIMAP4)
  PRIVATE
    (* Private-Deklarationen *)
    OpenSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
  PUBLIC
    (* Public-Deklarationen *)
    PROCEDURE OpenEmail(VAR IMAPClientExtd: TEmailCoreObject);
    PROCEDURE CloseEmail(VAR IMAPClientExtd: TEmailCoreObject);
  END;
Nun einige Fragen:
- Wenn ich eine Instanz von TEmailCoreObject erzeuge, ist dann das CREATE nur
für diese Instanz notwendig oder zusätzlich auch für TidIMAP4 ?
- Die Klasse TEmailCoreObject kommt auch als Parameter in den Methoden vor,
z.B. in OpenEmail(..). Ist das ein unzulässiger Schwanzbeisser oder geht das ?
- Wie kann ich ganz einfach feststellen, ob ein Objekt richtig erzeugt wurde ?
(am liebsten mit Debugger)

hoika 3. Jan 2021 23:15

AW: Zugriff auf Objekt in Klasse
 
Hallo,
schreib ins Create ein inherited Create,
dann gilt das Create für beide.

Schwanzbeisser, ja
Warum das Objekt als Parameter an das gleiche Objekt/Klasse übergeben?

Initialisiertes Objekt erkennen?
Setze es auf NIL sonst erkennst du es nicht.

FediDelPr 3. Jan 2021 23:27

AW: Zugriff auf Objekt in Klasse
 
@hoika

Schwanzbeisser:

- Ich möchte möglichst alles in das Modul verpacken, auch das Create!

- Der einzige Zugriff soll (vorderhand) über OpenEmail und CloseEmail erfolgen,
später dann noch Setup, Read und Write. Ich benötige aber gleichzeitig mehrere
EmailProvider, daher mehrere IMAPClients.

Vielleicht hast du weiteren Tipp /Lösungsweg ?

FediDelPr 3. Jan 2021 23:40

AW: Zugriff auf Objekt in Klasse
 
Noch etwas:

Vorderhand, während Entwicklung, möchte ich auch ausserhalb des Email-Moduls
vollen Zugriff auf TidIMAP4 um alle Funktionen des IMAP4 Drivers verwenden
zu können.

hoika 4. Jan 2021 06:28

AW: Zugriff auf Objekt in Klasse
 
Hallo,
Zugriff auf IMAP4 hast du ja durch die Ableitung.
Und mehere Konten = mehrere eigene Klassen, pro Konto eine.

Aber:
Bevor du mit deinen ganzen eigenen Dachen anfängst,
würde ich erst mal alles mit dem originalen Indy TIdImap4 zusammenbauen und dann deine eigene Klasse erzeugen.

haentschman 4. Jan 2021 07:34

AW: Zugriff auf Objekt in Klasse
 
Moin...:P
Es ist zwar löblich das Üben in einen sinnvollen Kontext zu packen. :thumb: Das hilft dir nicht weiter. Du brauchst Grundlagen!
Zitat:

Wenn ich eine Instanz von TEmailCoreObject erzeuge, ist dann das CREATE nur
Jede eigene Klasse muß/sollte einen constructor/destructor haben...auch wenn da erstmal nix drinsteht als inherited.
Was das bedeutet: siehe https://www.delphi-treff.de/tutorial...i-crashkurs/8/ -> Konstruktor
Noch Lesestoff:
https://www.delphipraxis.net/10691-o...inherited.html
:wink:

FediDelPr 4. Jan 2021 17:59

AW: Zugriff auf Objekt in Klasse
 
@hoika
das Arbeiten mit dem Indy TIdIMAP4 funktioniert grundsätzlich.
Nur will ich ein einfacheres und anwenderfreundlicheres Interface dazu.
Gewisse Details dürfen versteckt bleiben.
In den bisherigen Anwendungen zeigte sich was für mich wichtig ist, darum
möchte ich nicht immer den ganzen Ballast mitschleppen.

@hoika, haentschman
Ich programmiere seit einem halben Jahrhundert (was an und für sich noch nichts
heissen will). Es ist einfach so, dass OOP mich noch nicht so richtig überzeugt hat.
Trotzdem will ich den Einstieg jetzt mal definitiv durchziehen. Auch, damit ich mir
selbst ein Bild von den Vor- und Nachteilen machen kann. Bis anhin sehe ich vorallem
die Nachteile.
Bis jetzt habe ich eher den Eindruck von viel Ballast und - was ich hasse: unsichere
und unzuverlässige Software. Wohlverstanden immer mit dem gleichen Aufwand.
Auch bezüglich der besseren Lesbarkeit bin ich noch nicht überzeugt. Aber warten wir ab,
vielleicht komme ich noch auf den Geschmack. Etwas verwundert bin ich auch, dass mir der
Einstieg nicht eins, zwei, drei gelingt. Hat das mit dem Alter, Eingefahrenheit oder
damit zu tun, dass doch nicht alles so logisch und konsistent ist ? Kann auch sein, dass
ich noch nicht die für mich richtige Literatur gefunden habe.
Nun ich mache weiter und werde weitere Fragen stellen.

Bis dahin herzlichen Dank

TurboMagic 5. Jan 2021 08:48

AW: Zugriff auf Objekt in Klasse
 
Hallo,

wenn du die Grundlagen noch sicherer drauf hast, ist's kein wirklicher ballast mehr.
Deine Klasse erbt ja eigentlich alles von der entsprechenden Indy-Klasse, du solltest halt
nur wie schon beschrieben einen Constructor spendieren und in dem inherited aufrufen, damit
der geerbte Constructor der Indy-Klasse auch aufgerufen wird. Dannb rauchst du vermutlich bei
deinen Methoden keine Objektinstanzen mehr als Parameter, das macht dann alles die eigene Klasse.

Allerdings: durch das Erben sind bei deiner Klasse halt auch alle Dinge, welche die Indy-Klasse
als public anbietet weiterhin public.

Wenn dir das nicht passt kannst du alternativ eine Klasse schreiben die nicht erbt, sondern
intern eine Instanz der betreffenden Indy-Klasse nutzt die im COnstructor erzeugt wird und im
Destructor freigegeben wird.

Dann schreibst du nur für die DInge, die bei dir öffentlich sein soll entsprechende Wrapper-Methoden.

Grüße
TurboMagic

freimatz 5. Jan 2021 09:48

AW: Zugriff auf Objekt in Klasse
 
Wenn er kaseln will würde ich das auch eher vorschlagen (https://de.wikipedia.org/wiki/Kompos..._von_Vererbung)

FediDelPr 6. Jan 2021 14:10

AW: Zugriff auf Objekt in Klasse
 
Nun ich gehe jetzt tiefer in die Materie, es bringt ja nichts, wenn ich es nur
halb verstehe. Bin an Übungen mit dem Doberenz Delphi 7 Buch.
Das Tutorial des Delphi-Treffs kann ich nicht mehr runterladen. Weiss jemand wo
das noch möglich ist ?

Zugleich muss ich vorwärts kommen.
Daher nun zu weiteren Schwierigkeiten. Für das aktuelle Problem bin ich nahe am Ziel.
In der folgenden Version läuft's nämlich:

Code:
(* Deklaration und Aufruf *)

VAR
  IMAPClientEx: TEmailCoreObject;
  ...

 BEGIN
   IMAPClientEx := TEmailCoreObject.Create(NIL);
   IMAPClientEx.OpenEmail;
   ..
   ..
 END;

(* Klassendefinition und Implementation (in eigenem Modul) *)
TYPE
  TEmailCoreObject = CLASS(TidIMAP4)
  PRIVATE
    (* Private-Deklarationen *)
    ..
  PUBLIC
    (* Public-Deklarationen *)
    PROCEDURE OpenEmail;
    PROCEDURE CloseEmail;
  END;
Es wurde mir klar, dass die 'Übergabe' einer Instanz eigentlich einer Parameterübergabe
entspricht. Daher können auch die Parameter in OpenEmail usw.entfallen. (wie von TurboMagic gesagt)

Was mir an dieser Realisierung noch nicht passt, ist, dass das Create im Aufrufteil
stattfindet. Das muss in das Modul mit der Klassendefinition rein. Wie dieses Create-Zeile
aussieht ist mir noch nicht klar. Der Compiler frisst zwar folgendes, aber die Referenz der Instanz
verschwindet natürlich im Nirvana.

Code:
(* Deklaration und Aufruf *)

VAR
  IMAPClientEx: TEmailCoreObject;
  ...

 BEGIN
   IMAPClientEx.OpenEmail;
   ..
   ..
 END;

(* Klassendefinition und Implementation (in eigenem Modul) *)
TYPE
  TEmailCoreObject = CLASS(TidIMAP4)
  PRIVATE
    (* Private-Deklarationen *)
    ..
  PUBLIC
    (* Public-Deklarationen *)
    PROCEDURE OpenEmail;
    PROCEDURE CloseEmail;
  END;

PROCEDURE OpenEmail;
 BEGIN
   TEmailCoreObject.Create(NIL); (* geht nicht, funktionierende Alternative ? *)
   ..
   ..
 END;
Vielleicht hat das jetzt mit dem anscheinend notwendigen (oder mindestens empfehlenswerten) CONSTRUCTOR
zu tun? Auch das SELF könnte ein Kandidat zur Lösung des Problems sein.

Grüsse

TiGü 6. Jan 2021 14:29

AW: Zugriff auf Objekt in Klasse
 
Die Tutorials gehen doch? Zumindest kann ich problemlos z. B. das folgende aufrufen:

https://www.delphi-treff.de/tutorial...i-crashkurs/8/

Delphi-Quellcode:
(* Deklaration und Aufruf *)

// jeder soll formatieren wie er kann und mag, aber dieses UPPERCASE der Schlüsselwörter ist irgendwie ganz schwer
// TurboPascal aus den Achtzigern. Da wird der Bildschirm vor dem inneren Auge schwarz und die Schrift giftgrün
// und auf auf 80 Zeichen pro Zeile begrenzt ;-)

VAR
  IMAPClientEx: TEmailCoreObject;
  ...

 BEGIN
   IMAPClientEx := TEmailCoreObject.Create(nil);
   IMAPClientEx.OpenEmail;
   ..
   ..
  // wenn fertig, freigeben:
  IMAPClientEx.Free;
 END;

(* Klassendefinition und Implementation (in eigenem Modul) *)
TYPE
  TEmailCoreObject = CLASS(TidIMAP4)
  PRIVATE
    (* Private-Deklarationen *)
    ..
  PUBLIC
    (* Public-Deklarationen *)
    PROCEDURE OpenEmail;
    PROCEDURE CloseEmail;
  END;

PROCEDURE TEmailCoreObject.OpenEmail; // < - - - - Hier die Änderung beachten
 BEGIN
   // hier jetzt die eigentliche Logik implementieren.
   ..
   ..
 END;

FediDelPr 6. Jan 2021 14:38

AW: Zugriff auf Objekt in Klasse
 
@TiGü und andere

Entschuldigung, das habe ich unvollständig kopiert bzw. abgeschrieben.
Das ist schon mit der Klasse vorne dran.

FediDelPr 6. Jan 2021 14:41

AW: Zugriff auf Objekt in Klasse
 
@TiGü

Du schon recht, das einzelne Tutorial lässt sich schon runterladen. Was nicht geht
ist der Download des Delphi-Starter.

TiGü 7. Jan 2021 10:28

AW: Zugriff auf Objekt in Klasse
 
Du meinst dieses PDF-Buch?
Naja, da verpasst man jetzt auch nichts.

FediDelPr 8. Jan 2021 15:59

AW: Zugriff auf Objekt in Klasse
 
An meinem letzten Problem stehe ich immer noch an, trotz lesen in
mehreren Büchern.

Im Hauptmodul soll's so aussehen, kein Create:

Code:
VAR
  IMAPClientEx: TEmailCoreObject;
  ...

 BEGIN
   IMAPClientEx.OpenEmail;
   ..
   ..
 
 END;

Das Untermodul (EmailCore) soll so aussehen:

Code:
UNIT EmailCore;

TYPE
  TEmailCoreObject = CLASS(TidIMAP4)
  PRIVATE
    (* Private-Deklarationen *)
    ..
  PUBLIC
    (* Public-Deklarationen *)
    // hier CONSTRUCTOR notwendig ?? Wie genau ?  <---
    PROCEDURE OpenEmail;
    ..
  END;

PROCEDURE TEmailCoreObject.OpenEmail;
 BEGIN
   // Was muss hier eingefuegt werden, damit der Speicher für TEmailCoreObject
   // reserviert wird ?   <---
   ..
   ..
 END;
Kann da jemand konkret weiterhelfen ? Danke

Klaus01 8. Jan 2021 16:21

AW: Zugriff auf Objekt in Klasse
 
warum sträubst Du dich so gegen ein Create?

Delphi-Quellcode:
VAR
  IMAPClientEx: TEmailCoreObject;
  ...

 BEGIN
   IMAPClientEx := TEmailCoreObject.Create;
   try
     IMAPClientEx.OpenEmail;
     ..
     ..
   finally
    IMAPClientEx.Free;
   end;
 
 END;
Wenn Du kein Create haben möchstes musst Du Klassen-Methoden erstellen.
Dann könnte es so gehen.

Grüße
Klaus

FediDelPr 8. Jan 2021 16:46

AW: Zugriff auf Objekt in Klasse
 
Weil das nur ein technisches Problem (endlicher Speicher) ist und nichts mit der eigentlichen
Aufgabe zu tun hat. Es verhunzt die eigentliche Absicht. Die Essenz des Programmes
versinkt in solchen technischen Details. Das Programm ist schlussendlich schlechter lesbar,
es sind mehr Fehler möglich. Natürlich mag das für einen Einzelfall nicht grafierend sein
aber in der Summe.. Eine normale Variable muss man ja auch nicht zuerst kreiieren.

Ich mag diesen Ballast nicht, so ähnlich ist es ja auch mit der Fehlerverarbeitung. Auch die
ist so dominant, obwohl es eigentlich nur um die Ausnahmen geht.

Ich bin da ein Purist und würde sogar soweit gehen, dass dies ein Teil unserer heutigen
Softwarekrise ist.

Um es zu verdeutlichen ein Beispiel - der Zugriff auf eine Festplatte:

- Oeffnen (mit moeglichst wenigen Parametern, oder allenfalls Setup)
- Lesen oder Schreiben
- Schliessen

Das ist die Hauptstruktur, nichts weiter. Und die muss möglichst sichtbar bleiben.
Details dann in tieferen Schichten und auch dort dasselbe.

Ich hoffe du verstehst mich nicht falsch. Ich finde es wird gerade in der
Software-Industrie oft viel zu kompliziert gedacht. Ich könnte jetzt ein weiteres Mal
Einstein zitieren...

Grüsse

FediDelPr

FediDelPr 8. Jan 2021 16:48

AW: Zugriff auf Objekt in Klasse
 
Ah danke noch, dann schau ich mal bei den Klassen-Methoden

FediDelPr 9. Jan 2021 21:07

AW: Zugriff auf Objekt in Klasse
 
Gesetzt den Fall ich verzichte auf das Create im aufrufenden Modul,

Code:
VAR
  IMAPClientEx: TEmailCoreObject;
  ...

 BEGIN
   // IMAPClientEx := TEmailCoreObject.Create(nil); --> kein Create
   IMAPClientEx.OpenEmail;
   ..
kann ich eine Methode trotzdem erreichen oder nicht ? Ist also der Einsprung trotzdem
garantiert oder geht der Aufruf quasi ins Leere (weil nicht definiert) ?
Beim Debugging war das erfolgreich. Zufall ?

haentschman 10. Jan 2021 06:55

AW: Zugriff auf Objekt in Klasse
 
Moin...:P
Zitat:

kann ich eine Methode trotzdem erreichen oder nicht
Du kannst doch nicht ein Auto einsteigen (OpenEMail) wenn du es nicht produziert hast (Create)! :zwinker:
Zur dynamischen Verwendung einer Klasse/Objekt gehört immer ein Create/Free. Bei dieser Konstellation hast du die Wahl wann das Objekt im Speicher aufgenommen wird (Create) und wieder entfernt wird (Free).
Zitat:

Beim Debugging war das erfolgreich. Zufall ?
Wenn das so wäre, erzählst du uns nur die Hälfte. Bei diesen obigen Code, ohne Create, bekommst du definiv eine Zugriffsverletzung!
Zitat:

Weil das nur ein technisches Problem (endlicher Speicher) ist und nichts mit der eigentlichen Aufgabe zu tun hat.
Auch deine Main Form, und alle anderen automatisch erzeugten, liegen schon im Speicher. Besser wäre es wenn nur die Formulare erzeugt werden wenn sie gebraucht werden und wieder aus dem Speicher entfernt werden. Alle Forms haben ein Create/Free...nur macht das Delphi im Hintergrund. :zwinker:
Zitat:

versinkt in solchen technischen Details.
...das nennt man programmieren und nicht Klick Bunti. :stupid: :zwinker:
Zitat:

Eine normale Variable muss man ja auch nicht zuerst kreiieren.
Auch für eine Variable wird Speicher reserviert...im Hintergrund.

Wie schon mehrfach gesagt:
Delphi-Quellcode:
type
  TEmailCoreObject = class(TidIMAP4)
  private
  public
    constructor Create(Owner: TComponent);
    destructor Destroy; override;
    procedure OpenEmail;
  end;


implementation

constructor TEmailCoreObject.Create(Owner: TComponent)
begin
  inherited Create(Owner) // immer erste Zeile -> Erzeugen Vorfahr TidIMAP4
  //
end;

destructor TEmailCoreObject.Destroy;
begin
  //
  inherited; // immer letzte Zeile
end;
.
.
.
procedure TfoMain.Blubb;
var
  IMAPClientEx: TEmailCoreObject;

begin
  IMAPClientEx := TEmailCoreObject.Create(nil);
  try
    IMAPClientEx.OpenEmail;
  finally
    IMAPClientEx.Free;
  end;
end;
Stell den gesamten Code mal ein.

hoika 10. Jan 2021 07:24

AW: Zugriff auf Objekt in Klasse
 
Hallo,
ich glaube der TE verwechselt Debuggen mit Compilieren.

Wenn Du ohne Create arbeiten willst,
Musst du die Klasse über den Delphi-Designer auf das DataModul packen.

Davon raten dir hier alle ab.
Jetzt musst du halt entscheiden.

haentschman 10. Jan 2021 07:40

AW: Zugriff auf Objekt in Klasse
 
Zitat:

Musst du die Klasse über den Delphi-Designer auf das DataModul packen.
@TE: Zum Verständnis. Auch bei dieser Variante wird ein Create/Free ausgeführt...im Hintergrund. :zwinker: Das Objekt ist immer im Speicher, mit Create des DataModules, auch wenn es nicht benutzt wird!

Nochmal zu Klassenmethoden:
https://www.delphi-treff.de/tutorial...i-crashkurs/8/
Zitat:

Klassenmethoden

Es kann manchmal sinnvoll sein, dass man eine Methode nicht über die Instanz einer Klasse aufrufen möchte, sondern nur über die Klasse. So könnte man sich vorstellen, dass die Klasse „TgeomForm“ eine Methode „dimension“ besitzt, welche zurückgibt, welche Dimension die geometrischen Objekte besitzen, die durch diese Klasse dargestellt werden. Das Ergebnis dieser Methode wäre nicht abhängig von einer Instanz, sondern für die gesamte Klasse identisch.
Möchte man eine solche Methode haben, so leitet man sie bei der Deklaration mit dem Schlüsselwort „class“ ein.

type
TgeomForm = class
{...}
public
class function dimension : Integer;
end;

{...}

class function TgeomForm.dimension : Integer;
begin
result := 2;
end;

Selbstverständlich kann man in Klassenmehtoden nicht auf die Eigenschaften einer Klasse zuzugreifen, da diese nur existieren, wenn man mit Instanzen arbeitet!
PS: Der Tippfehler aus Seite kopiert. :zwinker:

Frage:
Wie oft wird das Objekt benutzt? Je nach Verwendung kann man das Objekt direkt vor OpenMail erzeugen und direkt wieder freigeben oder z.b. im constructor der Form oder der Logik Klasse erzeugen und am Ende (jeweiliger destuctor) wieder freigeben. Damit hat man das Objekt über die Lebensdauer der Form z.B. im Zugriff ohne ständig Create/Free. :zwinker:

brechi 10. Jan 2021 09:19

AW: Zugriff auf Objekt in Klasse
 
Für deinen Fall kannst du auch einen singleton implementieren (oder eine globale variable mit initialization und finalization nutzen), aber auch ich rate dir davon ab...

jfheins 10. Jan 2021 10:25

AW: Zugriff auf Objekt in Klasse
 
Zitat:

Zitat von FediDelPr (Beitrag 1480308)
Ich programmiere seit einem halben Jahrhundert (was an und für sich noch nichts
heißen will). Es ist einfach so, dass OOP mich noch nicht so richtig überzeugt hat.
Trotzdem will ich den Einstieg jetzt mal definitiv durchziehen. Auch, damit ich mir
selbst ein Bild von den Vor- und Nachteilen machen kann. Bis anhin sehe ich vor allem
die Nachteile.
Bis jetzt habe ich eher den Eindruck von viel Ballast und - was ich hasse: unsichere
und unzuverlässige Software. Wohlverstanden immer mit dem gleichen Aufwand.

Ich kann wenig zu IdIMAP beitragen, aber vielleicht einige generelle Punkte:
- Unsichere / unzuverlässige Software lässt sich in erster Linie mit einem Instrument bekämpfen: Tests. Am besten automatisierte, zuverlässige (deterministische) häufige, umfangreiche Tests.

OOP hat damit nur sehr am Rande etwas zu tun. OOP bietet mMn vor allem eine Gruppierung von Methoden mit einem Zusammenhang an. Wo man "früher" einen struct erstellt hat und dann 7 Funktionen hatte, die den als Parameter bekommen, kann man heute eine Klasse erstellen und die Methoden mit den Daten zusammen in einer Datei ablegen.

Zitat:

Weil das nur ein technisches Problem (endlicher Speicher) ist und nichts mit der eigentlichen
Aufgabe zu tun hat. Es verhunzt die eigentliche Absicht. Die Essenz des Programmes
versinkt in solchen technischen Details. Das Programm ist schlussendlich schlechter lesbar,
es sind mehr Fehler möglich. Natürlich mag das für einen Einzelfall nicht gravierend sein
aber in der Summe.. Eine normale Variable muss man ja auch nicht zuerst kreieren.
Den endlichen Speicher hast du aber quasi immer und überall. Und die Herausforderung ist ja, dass jeder den Speicher anders nutzen will.
Wenn du keine dynamische Speicherallozierung machst, dann musst du für jede Sache beim Compilieren festlegen, wieviele verschiedene Sachen es geben darf. Also Chrome würde bspw. mit maximal 20 Tabs laufen weil das Array hat auf 20 Elemente gesetzt ist. In echt möchte aber der eine Type 50 schlanke Tabs laufen lassen, der zweite nur einen Tab aber der rechnet irre viel und der dritte kauft sich extra 64GB RAM um 500 Tabs parallel anzuzeigen.
Daher gibt es dynamisches Speichermanagement, damit jeder das machen kann, was er will ;-)

Und dazu gehört dann auch immer Speicher allozieren und freigeben. Vergleiche einmal Pseudocode:
Code:
var myParams = malloc(TmyParams);
myParams.Recipient = "a@b.com"
SendEmail(myParams);
Free(myParams);
Code:
var myParams = TmyParams.Create();
myParams.Recipient = "a@b.com"
myParams.SendEmail();
myParams.Free;
Ist quasi dasselbe, nur anders aufgeschrieben. Das Problem, was hier gelöst wird: Es wird Speicher für Variablen reserviert, die länger leben als ein Funktionsaufruf. Denn letztlich kennt der C und der Delphi Compiler die zwei Optionen: Variable lebt genau so lange wie die Funktion (Stack) oder Variable lebt länger => Heap & Programmierer muss sich darum kümmern, den Speicher wieder aufzuräumen.

Wenn dir das Speichermanagement zuviel wird, würde ich dir eine andere Sprache empfehlen. Eine mit automatischem Speichermanagement. Dann musst du immer noch allozieren, aber nicht mehr freigeben. Die Auswahl ist riesig und wird immer größer. (Mir wäre keine neue Sprache bekannt, die dem Entwickler das aufbürdet) Eine Auswahl:
- Rust
- Javascript / Typescript
- C#
- Kotlin
- Python
- Oxygene?

Der Code wird lesbarer weil du dich um das freigeben nicht mehr kümmern musst.

TurboMagic 10. Jan 2021 10:37

AW: Zugriff auf Objekt in Klasse
 
Automatisches Speichermanagement klingt zwar in der Theorie schön, hat in der Praxis aber durchaus auch seine Tücken.
Ein gutes Beispüiel dafür war die Delphi 2006 IDE...
Denn: der Speicher wird nicht deterministisch sondern meist irgendwann (Ausnahme: ARC) freigegeben.
Bis dahin hat sich etvl. viel "Müll" angesammelt oder die Freigabe passiert zu einem Zeitpunkt wo der Garbage Collector
meint es wäre oppertun, es aber in Wirklichkeit doch nicht ist...

TurboMagic 10. Jan 2021 10:44

AW: Zugriff auf Objekt in Klasse
 
Zugriff auf nicht erzeugte Objektreferenzen wird eher zeitnah knallen!
Einfach nicht so gegen das Create sträuben!
Du kannst halt auch nicht in der Bibliothek ein Buch ausleihen ohne den Ausleihvorgang irgendwie zu registrieren...

Und was Exceptionbehandlung anbelangt: die ist eigentlich weniger aufdringlich als die klassische
Fehlerbehandlungsmethode.

Warum?

Weil man früher direkt nach jedem Aufruf der schief gehen konnte eine Statusvariable (in Turbo Pascal IOresult,
in SAP's ABAP Sy-Subrc) direkt abfragen musste und dann dort den Fehler gleich behandeln musste weil er sonst
nach dem nächsten Aufruf einer Routine die diese Fehlerbehandlung nutzt überschrieben ist.

Bei Exceptions kann man mitunter auch eine zentrale Behandlung irgendwo implementieren und alle Exceptions
laufen dort auf, egal woher die kommen. Man kann auch Fehler durch unterschiedliche Exception Klassen unterscheiden
und nur die behandeln, die man für relevant hält. Diese Klassen können dann auch zusätzliche Daten die Infos
zur Fehlerursache enthalten bekommen usw. ALles Dinge, die der klassische Ansatz nicht bietet.
Der lenkt vielstärker von der eigentlichen Aufgabe ab als so ein Create Aufruf...


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:42 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