AGB  ·  Datenschutz  ·  Impressum  







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

Record-Variable in Klasseninstanz setzen

Ein Thema von Perlsau · begonnen am 9. Dez 2012 · letzter Beitrag vom 10. Dez 2012
Antwort Antwort
Seite 1 von 2  1 2      
Perlsau
(Gast)

n/a Beiträge
 
#1

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 13:27
Ich vermute mal, daß das AfterScroll-Event vor dem DataModuleCreate ausgelöst wird (passiert, wenn das DataSet zur DesignTime auf Active gesetzt ist). Damit wäre die Instanz von MainZu noch nicht erstellt und es kommt zu der Schutzverletzung.
Das hatte ich zu allererst überprüft: Die Datenbankverbindung wird erst nach dem Start in OnShow hergestellt. Ich achte immer darauf, daß die Verbindungskomponente (hier ADOConnection zur Verbindung mit einem MsSQL-Server) nicht zufällig auf connected := true steht, weil ich vielleicht zuvor im Feld-Editor eines Datasets war und dort was manipuliert habe. Das ist bei mir schon Routine, vor dem Betätigen der F9-Taste, wenn ich zuvor im Datenmodul zugange war, die Connect-Komponente zu überprüfen. Beim Setzen auf false werden ja auch alle offenen Datasets inaktiv ... Außerdem würden, wenn deine Vermutung zuträfe, auch die anderen Proceduren wie z.B. Set_StatusBar, die ja funktionieren, eine Zugriffsverletzung auslösen.

So wie ich's nun gelöst habe, ist es sowieso viel übersichtlicher: Die Variablen, die andere Units bzw. Klassen über den Zustand der Datenbank informieren sollen, lege ich im Datenmodul ab. Von dort holt sich die Klasse TMainTools alle notwendigen Informationen.
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#2

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 16:40
Wird denn die Variable von TMain_Zugriff
VAR
User_Tab : TTab_User;

initialisiert?
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#3

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 17:09
Wird denn die Variable von TMain_Zugriff User_Tab : TTab_User; initialisiert?
Inzwischen befindet sich die Variable nicht mehr in TMain_Zugriff, sondern in TDatMod (Datenmodul). Die Initialisierung hat sich jedoch nicht geändert, sie erfolgt nach wie vor aus der Unit MainTools heraus (mit DatMod. statt wie zuvor mit MZGF.), die alle Datenbank-Aktionen des Hauptformulars übernimmt:

Delphi-Quellcode:
procedure TMainTools.Einstellungen_Setzen;
CONST
     N = '0';
VAR
   i,z,
   Links,
   Oben,
   Breit,
   Hoch : Integer;
   Maximiert : Boolean;
   Aus : String;

begin
     IF NOT DatMod.Aset_Benutzer.Active THEN EXIT;

     Rec_User.User_Index := DatMod.Aset_Benutzer.FieldByName('Idx_Benutzer').AsInteger;
     Rec_User.Name := DatMod.Aset_Benutzer.FieldByName('Name').AsString;
     Rec_User.Pass := DatMod.Aset_Benutzer.FieldByName('Passwort').AsString;

     Links := DatMod.Aset_Benutzer.FieldByName('Links').AsInteger;
     Oben := DatMod.Aset_Benutzer.FieldByName('Oben').AsInteger;
     Breit := DatMod.Aset_Benutzer.FieldByName('Breit').AsInteger;
     Hoch := DatMod.Aset_Benutzer.FieldByName('Hoch').AsInteger;
     Maximiert := DatMod.Aset_Benutzer.FieldByName('Maximiert').AsBoolean;

     MZGF.Set_FormMain(Links, Oben, Breit, Hoch, Maximiert);

     IF NOT DatMod.Aset_UserTabs.Active THEN EXIT;
     IF NOT DatMod.Aset_UserTabs.Locate('Idx_User_Tabs',Rec_User.User_Index,[]) THEN EXIT;

// Filmtitel - Initialisierung von User_Tab
     DatMod.User_Tab.Titel_Index := DatMod.Aset_UserTabs.FieldByName('Titel_Index').AsInteger;
     DatMod.User_Tab.Titel_SortIndex := DatMod.Aset_UserTabs.FieldByName('Titel_SortIndex').AsInteger;
     DatMod.User_Tab.Titel_SortOrder := NOT DatMod.Aset_UserTabs.FieldByName('Titel_SortOrder').AsBoolean;
     DatMod.User_Tab.Titel_SortText := DatMod.Aset_UserTabs.FieldByName('Titel_SortText').AsString;

     DatMod.Aset_Titel.Locate('Idx_Titel',DatMod.User_Tab.Titel_Index,[]);
     Sortieren_FilmTitel(DatMod.User_Tab.Titel_SortIndex);

     z := MZGF.Spalten_Filmtitel -1;
     FOR i := 0 TO z DO
     BEGIN
          Aus := IntToStr(i);
          IF i < 10 THEN Aus := N + Aus;
          Aus := 'Tab_Titel_' + Aus;
          MZGF.Set_Spalte_FilmTitel(i,DatMod.Aset_UserTabs.FieldByName(Aus).AsInteger);
     END;
end;
Was ich nicht verstanden hatte: Wieso funktionierte ein ähnliches Konstrukt in einer anderen Klasse (und Unit) vom Hauptformular aus und das im ersten Post gezeigte Konstrukt vom Datenmodul aus nicht?

Das AfterScroll-Ereignis im Datenmodul wird bereits vor dem Setzen der Werte in MainTool ausgelöst, nach dem ersten Dataset.Open (korrekt: DatMod.User_Tab.Active := true) wird es garantiert ausgelöst – so dürfte der nicht-initialisierte Zustand der Variablen aber dennoch keine Rolle spielen, da der Wert der Variablen ja nicht ausgelesen, sondern gesetzt wird ... Das war es doch, worauf deine Frage zielte, oder?

Ich glaub ich muß für heute mal aufhören, sitze schon seit 5:30 hier ...
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 17:58
Außerdem würden, wenn deine Vermutung zuträfe, auch die anderen Proceduren wie z.B. Set_StatusBar, die ja funktionieren, eine Zugriffsverletzung auslösen.
Nicht zwingend! Solange diese Methoden keine Felder der Instanz ansprechen, funktionieren die auch wenn die Instanz nicht initialisiert ist. (Wobei man sich dann aber fragen muss, warum sie nicht als Klassenmethoden realisiert sind bzw. überhaupt zu der Klasse gehören.)
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#5

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 18:45
Außerdem würden, wenn deine Vermutung zuträfe, auch die anderen Proceduren wie z.B. Set_StatusBar, die ja funktionieren, eine Zugriffsverletzung auslösen.
Nicht zwingend! Solange diese Methoden keine Felder der Instanz ansprechen, funktionieren die auch wenn die Instanz nicht initialisiert ist. (Wobei man sich dann aber fragen muss, warum sie nicht als Klassenmethoden realisiert sind bzw. überhaupt zu der Klasse gehören.)
Set_StatusBar gehört zur Klasse TMain_Zugriff, wie du im ersten Code-Fenster meines ersten Postings leicht feststellen kannst ...
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 21:35
Zeig mal den constructor von TMain_Zugriff.

Probier eventl. mal das. Wenn das funzt liegt Uwe wohl richtig:

Delphi-Quellcode:
procedure TDatMod.DataModuleCreate(Sender: TObject);
begin
  Aset_TitelAfterScrollFlag:= false;
  MainZu := TMain_Zugriff.Create;
  Aset_TitelAfterScrollFlag:= true;
end;

procedure TDatMod.Aset_TitelAfterScroll(DataSet: TDataSet);
begin
   if Aset_TitelAfterScrollFlag then
   begin
     ..
   end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#7

AW: Record-Variable in Klasseninstanz setzen

  Alt 10. Dez 2012, 02:09
Mann ist das ein Kuddelmuddel in dem Sourcecode!
Ich versuche mal Ordnung zu schaffen.
Wir beginnen mit dem Record:
Delphi-Quellcode:
TTab_User = RECORD
  Titel_Index : Integer;
  Titel_SortIndex : Integer;
  Titel_SortOrder : Boolean;
  Titel_SortText : String;
END;
und stellen die wichtigste Frage:
Könnte es nicht sein, dass TTab_User nicht eine Klasse statt einen Records sein sollte?
Eine Klasse ist im Prinzip ein Record + Methoden.

Antwort: Ja, es gibt potentielle Methoden für die Klasse TTab_User:
Delphi-Quellcode:
// Filmtitel - Initialisierung von User_Tab
DatMod.User_Tab.Titel_Index := DatMod.Aset_UserTabs.FieldByName('Titel_Index').AsInteger;
DatMod.User_Tab.Titel_SortIndex := DatMod.Aset_UserTabs.FieldByName('Titel_SortIndex').AsInteger;
DatMod.User_Tab.Titel_SortOrder := NOT DatMod.Aset_UserTabs.FieldByName('Titel_SortOrder').AsBoolean;
DatMod.User_Tab.Titel_SortText := DatMod.Aset_UserTabs.FieldByName('Titel_SortText').AsString;
Und damit sieht die Klasse im 1. Entwurf so aus:
Delphi-Quellcode:
TTab_User = class(TObject)
public
  TitelIndex : Integer;
  SortIndex : Integer;
  SortOrder : Boolean;
  SortText : String;

  procedure LoadFromDataset(ds:TDataset);
  procedure SaveToDataset(ds:TDataset);
  procedure Clear;
END;

procedure TTab_User.LoadFromDataset(ds:TDataset);
begin
  TitelIndex:= ds.FieldByName('Titel_Index').AsInteger;
  SortIndex := ds.FieldByName('Titel_SortIndex').AsInteger;
  SortOrder := NOT ds.FieldByName('Titel_SortOrder').AsBoolean;
  SortText := ds.FieldByName('Titel_SortText').AsString;
end;
Der Anfang ist gemacht.
Die weiteren Schritte sehen so aus:
* aus den public Variablen werden Properties gemacht
* weitere Methoden (z.B. procedure Clear oder SaveToDataset)entdecken und zur Klasse hinzufügen
* überprüfen ob die Klasse vollständig ist (gibt es noch weitere Felder aus der Tabelle "User_Tab"?)
* den Sourcecode der Klasse in eine eigene Unit verschieben
* Ein Objekt der neuen Klasse TTab_User in die Klasse TMain_Zugriff einbauen
* überlegen ob ein Objekt von TTab_User ausreicht oder ob man nicht eine Liste von diesen Objekten braucht
* müssen TTab_User-Objekte kopiert werden können? Fall ja, von TPersistent ableiten und die Methode Assign überschreiben

Geändert von sx2008 (10. Dez 2012 um 02:13 Uhr)
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#8

AW: Record-Variable in Klasseninstanz setzen

  Alt 10. Dez 2012, 14:32
Mann ist das ein Kuddelmuddel in dem Sourcecode!
Ich versuche mal Ordnung zu schaffen.
Das geht mir schon so seit ich den Thread das erste Mal sah.
Das kann doch kein Mensch lesen. (Lesen ist was anderes als "mit Mühe Entziffern" )
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 22:36
Außerdem würden, wenn deine Vermutung zuträfe, auch die anderen Proceduren wie z.B. Set_StatusBar, die ja funktionieren, eine Zugriffsverletzung auslösen.
Nicht zwingend! Solange diese Methoden keine Felder der Instanz ansprechen, funktionieren die auch wenn die Instanz nicht initialisiert ist. (Wobei man sich dann aber fragen muss, warum sie nicht als Klassenmethoden realisiert sind bzw. überhaupt zu der Klasse gehören.)
Set_StatusBar gehört zur Klasse TMain_Zugriff, wie du im ersten Code-Fenster meines ersten Postings leicht feststellen kannst ...
Ich hatte nichts anderes behauptet. Es ist nur so, daß eine (nicht virtuelle) Methode einer Klasse nur dann eine initialisierte Instanz der Klasse benötigt, wenn sie auch auf Felder der Instanz zugreift. Würde die Methode z.B. lediglich ein MessageBeep aufrufen, dann funktioniert das auch wenn kein Create aufgerufen wurde. Die Tatsache, daß der Aufruf einer Methode einer Instanz funktioniert, heißt nicht zwingend, daß die Instanz initialisiert ist. Das kann man erst wissen, wenn man die Implementation der Methode kennt.

Übrigens: ein recht bekanntes Beispiel ist die Methode Free, die man auch aufrufen kann, wenn die entsprechende Instanzvariable nil ist.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Record-Variable in Klasseninstanz setzen

  Alt 9. Dez 2012, 23:34
Zum Testen:
Delphi-Quellcode:
type
  TFoo = class
  private
    FData : string;
    function GetData : string;
  public
    property Data : string read GetData;
  end;

function TFoo.GetData : string;
begin
  if Self = nil then
    Result := 'keine Instanz vorhanden'
  else
    Result := FData;
end;

procedure Test;
var
  LFoo : TFoo;
begin
  ShowMessage( LFoo.Data );
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  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 20:53 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz