Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   FreePascal Auf "überliegende" Klasse zugreifen ? (https://www.delphipraxis.net/181632-auf-ueberliegende-klasse-zugreifen.html)

stiftII 30. Aug 2014 17:55

Auf "überliegende" Klasse zugreifen ?
 
Hallo,
ich weiß nicht ob das überhaupt möglich ist was ich vorhabe, aber ich versuche es mal zu erklären :wink:

Ich habe ein Programm mit folgender Struktur.
Delphi-Quellcode:
    TUseFullClass = class
      public
        function DoSomething:boolean;     
    end;

    TMainClass = class
      usefullinfos:string;
      UsefullClass:TUsefullClass;
    end;  
   
   
   
   ........
   
   function Tusefullclass.DoSomething:Boolean;
   begin
      //Access TmainClasses "usefullinfos" String ??
   
   end;
Also 2 einfache Klassen, wobei die eine Klasse "TMainClass" die "TUseFullClass" deklariert.

Nun möchte ich wenn TUseFullClass in TMainClass deklariert ist auf Variablen von TMainClass zugreifen mit der Funktion DoSomething von TUseFullClass.

Geht das so überhaupt, oder gibt es eine bessere Möglichkeit das umzusetzen ?

Freue mich auf antworten :)

Grüße
stiftII

DeddyH 30. Aug 2014 18:02

AW: Auf "überliegende" Klasse zugreifen ?
 
Das ginge schon, aber wenn sich 2 Klassen gegenseitig kennen müssen, hat das immer ein "Geschmäckle". Was genau hast Du denn vor, evtl. könntest Du das über ein Event lösen?

Olli73 30. Aug 2014 18:07

AW: Auf "überliegende" Klasse zugreifen ?
 
Hilft dir das hier weiter?

Delphi-Quellcode:
   
    TMainClass = class;

    TUseFullClass = class
      private
        FMainClass: TMainClass;
      public
        function DoSomething:boolean;     
    end;

    TMainClass = class
      usefullinfos:string;
      UsefullClass:TUsefullClass;
    end;  
   
   
   
   ........
   
   function Tusefullclass.DoSomething:Boolean;
   begin
      //Access TmainClasses "usefullinfos" String ??
                FMainClass.UseFullInfos....
   
   end;
Zitat:

Also 2 einfache Klassen, wobei die eine Klasse "TMainClass" die "TUseFullClass" deklariert.
Die "Referenz" muss natürlich in obigem Beispiel dann auf beiden Seiten gesetzt werden.

Beachte aber auch den Kommentar von DaddyH.

Gruß,
Olli

Edit: Klassennamen waren vertauscht!

stiftII 30. Aug 2014 18:25

AW: Auf "überliegende" Klasse zugreifen ?
 
Danke für eure Antworten :)

Olli73: Der Code sieht ja ansich sehr gut aus, bloß leider bekomme ich sofort eine Zugriffsverletzung wenn ich dann auf Die Variablen von TMainClass zugreifen möchte.

Fehler ist: External: SIGSEGV

Mein Programm sieht jetzt so aus:
Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TMainClass = class;

    TUseFulClass = class
      private
        FMainClass: TMainClass;
      public
        function DoSomething:boolean;
    end;

    TMainClass = class
      usefulinfos:string;
      UsefulClass:TUsefulClass;
    end;



var
  Form1: TForm1;
  MainClass:TMainClass;

implementation

{$R *.lfm}

   { TForm1 }

   procedure TForm1.Button1Click(Sender: TObject);
   begin
      MainClass := TMainClass.Create;
      MainClass.usefulinfos:= 'Very useful Infos';
     Mainclass.usefulClass.DoSomething;
   end;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

   function Tusefulclass.DoSomething:Boolean;
   begin
      //Access TmainClasses "usefulinfos" String ??
      Form1.Caption:= FmainClass.usefulinfos;


   end;


end.
Ich glaube ich muss das irgendwie anders lösen ? :|

Olli73 30. Aug 2014 18:36

AW: Auf "überliegende" Klasse zugreifen ?
 
Hast du den Code gekürzt oder sieht der wirklich so aus?

Denn darin gibt es keine Konstruktoren und diese werden auch nicht aufgerufen (um die Instanzen/Objekte zu erstellen).

Gruß,
Olli

stiftII 30. Aug 2014 18:44

AW: Auf "überliegende" Klasse zugreifen ?
 
Hey :)
Ja der Code ist stark vereinfacht, beim Originalcode blickt man vermutlich nicht so gut durch.

Ja hatte vergessen .create aufzurufen. Habs aber schon reineditiert :)

Muss man beim Konstruktor irgendwas beachten, damit auf "FMainClass" von "TUsefullclass" zugegriffen werden kann ?

Olli73 30. Aug 2014 18:50

AW: Auf "überliegende" Klasse zugreifen ?
 
Ohne genau zu wissen, was du vorhast, kann dir keiner Tipps geben, wie du das sauber aufbauen kannst.

Aber grundsätzlich:

Du musst beide Objekte erstellen (create) und die Werte für FMainClass und UseFullClass entsprechend zuweisen (die müssen auf das jeweils andere Objekt, das du erstellst, zeigen).

Gruß,
Olli

Dejan Vu 30. Aug 2014 18:50

AW: Auf "überliegende" Klasse zugreifen ?
 
Nee, mach das nicht. Wenn A eine Eigenschaft von B ist, soll A keine Kenntnis von B haben. Wenn man so anfängt, sollte man es gleich sein lassen. denn 'A' könnte ja auch mal eine Eigenschaft von C sein, was aber nun nicht mehr wegen der Abhängigkeit zu B geht. Nee, nee.

Wenn die sich was zu sagen haben, dann soll 'A' ein Event bereitstellen, an das B sich hängen kann.
Und wenn 'A' etwas wissen muss, was auch 'B' weiß, dann soll 'B' das 'A' gefälligst mitgeben, z.B. so

Delphi-Quellcode:
Type
  TClassA = Class
  private
    fInfo : TInfo;
  public
    constructor Create (info : TInfo);
  end;

  TClassB = Class
  private
    FA: TClassA;
    FInfo : TInfo;
  public
    Constructor Create;
  end;

Constructor TClassB.Create;
Begin
   Finfo := TInfo.Create;
   FA := TClassA.Create(FInfo);
End;

DeddyH 30. Aug 2014 19:01

AW: Auf "überliegende" Klasse zugreifen ?
 
Habbich doch gesacht, nur kürzer :D

stiftII 30. Aug 2014 19:03

AW: Auf "überliegende" Klasse zugreifen ?
 
Danke nochmal.

Zitat:

Ohne genau zu wissen, was du vorhast, kann dir keiner Tipps geben, wie du das sauber aufbauen kannst.
Okay dann versuch ichs mal zu erklären :). Es soll ein Programm werden welches Pokertische verwaltet. Und es arbeitet mit einer Hauptklasse die 3 Threads aufruft.. So in Etwa:

Delphi-Quellcode:
    TMainClass = class
      ID:integer;
      UsefulThreadA:TUsefulThreadA;
      UsefulThreadB:TUsefulThreadB;
      UsefulThreadC:TUsefulThreadC;
      protected
        constructor Create;
    end;
Nun findet UsefulThreadA eine ID heraus und soll sie TMainClass übergeben. Sobald die Information zur Verfügung steht starten UsefulThreadB und UsefulThread C.

Also müssen UsefulThreadB und C wissen, was in TMainClass(.id) steht.

Zitat:

Wenn die sich was zu sagen haben, dann soll 'A' ein Event bereitstellen, an das B sich hängen kann.
Und wenn 'A' etwas wissen muss, was auch 'B' weiß, dann soll 'B' das 'A' gefälligst mitgeben, z.B. so
Das sieht echt super aus, ich glaube ich schreibe das ganze Programm etwas um und mache es dann so, dass ich die ID vorher hole und dann UsefulThreadB und UseFulThreadC im Constructor bei TMainClass mit übergebe.

Wobei ich glaube das das auch nicht optimal ist, da ich dann UsefulThreadA extern von meiner TMainClass hätte. Aber so würde es natürlich funktionieren.

Danke für eure Eingebungen :)

Olli73 30. Aug 2014 19:15

AW: Auf "überliegende" Klasse zugreifen ?
 
Zitat:

Zitat von stiftII (Beitrag 1270347)
Danke nochmal.
Okay dann versuch ichs mal zu erklären :). Es soll ein Programm werden welches Pokertische verwaltet. Und es arbeitet mit einer Hauptklasse die 3 Threads aufruft.. So in Etwa:

Delphi-Quellcode:
    TMainClass = class
      ID:integer;
      UsefulThreadA:TUsefulThreadA;
      UsefulThreadB:TUsefulThreadB;
      UsefulThreadC:TUsefulThreadC;
      protected
        constructor Create;
    end;
Nun findet UsefulThreadA eine ID heraus und soll sie TMainClass übergeben. Sobald die Information zur Verfügung steht starten UsefulThreadB und UsefulThread C.

Also müssen UsefulThreadB und C wissen, was in TMainClass(.id) steht.

Wenn das ganze auch noch in Threads ablaufen soll, darfst du sowieso nicht einfach aus dem Thread heraus auf MainClass zugreifen. Dann musst du das ganze mittels Synchronize und/oder CriticalSections absichern...

Gruß,
Olli

stiftII 30. Aug 2014 19:21

AW: Auf "überliegende" Klasse zugreifen ?
 
Hey danke für den Comment.
Ich benutze dafür CriticalSections. Wobei ich gelesen habe, dass es bei Lesezugriffen eigentlich keine Speicherverletzungen gibt.

Werds wohl jetzt so in etwa machen wie Dejan Vu beschrieben hat.

Allerdings schade, dass ich die andere Möglichkeit (Die ich zugegebenermaßen nicht ganz verstehe) nicht verwenden kann.

Programmcode sieht da so aus:
Falls mal jemand schauen mag warum das eine Zugriffsverletzung gibt.
Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TMainClass = class;

    TUseFulClass = class
      private
        FMainClass: TMainClass;
      public
        function DoSomething:boolean;
    end;

    TMainClass = class
      usefulinfos:string;
      UsefulClass:TUsefulClass;
      protected
        constructor Create;
    end;



var
  Form1: TForm1;
  MainClass:TMainClass;

implementation

{$R *.lfm}

   { TForm1 }
constructor TMainClass.Create;
begin
    UsefulClass := TUseFulClass.Create;
    //UsefulClass.FMainClass := TMainClass.Create; // Macht ja nicht so viel Sinn
end;

   procedure TForm1.Button1Click(Sender: TObject);
   begin
     MainClass := TMainClass.Create;
     MainClass.usefulinfos:= 'Very useful Infos';
     Mainclass.usefulClass.DoSomething;
   end;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

   function Tusefulclass.DoSomething:Boolean;
   begin
      //Access Violation
      Form1.Caption:= fmainClass.usefulinfos;


   end;


end.

Olli73 30. Aug 2014 19:32

AW: Auf "überliegende" Klasse zugreifen ?
 
Zitat:

Zitat von stiftII (Beitrag 1270351)
Delphi-Quellcode:
constructor TMainClass.Create;
begin
    UsefulClass := TUseFulClass.Create;
    //UsefulClass.FMainClass := TMainClass.Create; // Macht ja nicht so viel Sinn
end;

Delphi-Quellcode:
constructor TMainClass.Create;
begin
    UsefulClass := TUseFulClass.Create;
    UsefulClass.FMainClass := self; // aber das hier Würde zumindest funktionieren, auch wenn es etwas unschön ist, wie du an den anderen Kommentaren siehst
end;
Edit: Etwas besser wäre es, wenn du TUseFullClass einen entsprechenden Constructor mit Parameter "Owner" (bzw. "MainClass") hinzufügst und denn so aufrufst:
Delphi-Quellcode:
UsefulClass := TUseFulClass.Create(self);

stiftII 30. Aug 2014 21:27

AW: Auf "überliegende" Klasse zugreifen ?
 
Hey, das funktioniert ja wunderbar :D.

Danke nochmal für die Ausführungen :)

himitsu 30. Aug 2014 22:13

AW: Auf "überliegende" Klasse zugreifen ?
 
Zitat:

Zitat von Olli73 (Beitrag 1270338)
Hast du den Code gekürzt oder sieht der wirklich so aus?

Denn darin gibt es keine Konstruktoren und diese werden auch nicht aufgerufen (um die Instanzen/Objekte zu erstellen).

Wenn ihm die Standard-Constructoren vom TObject reichen, weil er im Constructor nichts machen will, dann braucht er natürlich sselber keine zu implementieren.


Da sich die Klassen aber gegenseitig kennen sollen, oder zumindestens die eine Klasse die Andere,
dann sollte man der einen Klasse schon einen Constructor geben, wo man ganz praktisch den Instanzzeiger der anderen Klase mitgeben könnte, welchen sie sich dann in einem privatem Feld speichert.

Also dein FMainClass wäre dann privat und nicht public verfügbar (maximal als ReadOnly-Property).

Olli73 30. Aug 2014 23:13

AW: Auf "überliegende" Klasse zugreifen ?
 
Zitat:

Zitat von himitsu (Beitrag 1270382)
Zitat:

Zitat von Olli73 (Beitrag 1270338)
Denn darin gibt es keine Konstruktoren und diese werden auch nicht aufgerufen (um die Instanzen/Objekte zu erstellen).

Wenn ihm die Standard-Constructoren vom TObject reichen, weil er im Constructor nichts machen will, dann braucht er natürlich sselber keine zu implementieren.

Anstatt "und diese werden nicht aufgerufen" meinte ich eigentlich "es werden überhaupt keine Konstruktoren aufgerufen" und deshalb hat er auch die Zugriffsverletzung bekommen; ein "create" hat er erst später ergänzt, wie man am "edit" sieht. Außerdem muss er ja irgendwie/irgendwo die (privaten) Felder füllen für den gegenseitigen Zugriff.

Zitat:

Da sich die Klassen aber gegenseitig kennen sollen, oder zumindestens die eine Klasse die Andere,
dann sollte man der einen Klasse schon einen Constructor geben, wo man ganz praktisch den Instanzzeiger der anderen Klase mitgeben könnte, welchen sie sich dann in einem privatem Feld speichert.
Hatte ich ja in meinem Edit zu #13 geschrieben - OK, ich habe vergessen zu erwähnen, dass er es sich dort im Konstruktor dann in einem privaten Feld speichern soll.

Gruß
Olli

Blup 1. Sep 2014 08:57

AW: Auf "überliegende" Klasse zugreifen ?
 
Zitat:

Zitat von stiftII (Beitrag 1270351)
Ich benutze dafür CriticalSections. Wobei ich gelesen habe, dass es bei Lesezugriffen eigentlich keine Speicherverletzungen gibt.

Sobald irgendwer die Variable beschreibt (z.B. der Hauptthread), während irgendein anderer Thread lesend auf die Variable zugreift, kann es krachen.
In einem solchen Fall gibt es keine direkte Zugriffsverletzung ("Speicherverletzungen" ist nicht das richtige Wort). Der gelesene Wert ist aber ungültig.
Ist das z.B. eine Variable die einen bestimmten Speicherbereich adressiert (z.B. ein Objekt), kann als Folge irgendwo eine Zugriffsverletzung auftreten.
Zumindest ist der weitere Programmverlauf dann nicht mehr vorhersehbar.


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