Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Überschreiben von Feldern in OOP (https://www.delphipraxis.net/91642-ueberschreiben-von-feldern-oop.html)

mojo777 8. Mai 2007 07:03


Überschreiben von Feldern in OOP
 
Hallo Leute,

habe momentan ein Problem mit der Vererbung.

Das Ziel ist es, z.b. Produkte, Warengruppen, Kunden, etc... als Objekte darzustellen, welche in einer Datenbank gepsichert sind.

Habe hierfür ein Minimalbeispiel erstellt. Statt viel rumzuschreiben, hier Bild:
http://pilaf.ath.cx/pub/shared_pics/klassen_1.gif

So. Ich will die Methode getPointerByUid in TItemListe implementieren, damit ich den selben Quatsch nicht 1000 mal tippen muss.
Diese Mthode sähe in TItemliste so aus:
Delphi-Quellcode:
function TItemListe.getPointerByUid(uid:Integer):Pointer;
  var i:INteger;
  begin
  for i:=1 to self.Count do
    begin
    if self.Liste[i-1].uid=uid then
      begin
      Result:=@self.Liste[i-1];
      exit;
      end;
    end;
  raise ERangeError.Create('Kein ItemListeneintrag gefunden! '+#13+'UID: '+IntToStr(uid));
  end;
Dabei sieht die TProdListe.Add methode so aus:

Delphi-Quellcode:
procedure TProdListe.add(bez:String; preis:Double; (...));
var i:Integer
begin
i:=length(self.Liste);
setLength(self.Liste, i+1);
self.Liste[i]:=TProdukt.Create(bez, preis, (...));
end;
Nun das Problem:

Wenn die Procedure getPointerByUid in TItemListe läuft, greift diese auf die Liste, deklariert in TItemliste zu. Das ist bad! Diese ist natürlich leer.


Sicherlich hat sich der eine oder andere mit diesem Modellproblemen schon beschäftigt. Wie macht ihr das?
Wäre für Vorschläge aller Art sehr dankbar!

Gruß!

sh17 8. Mai 2007 07:55

Re: Überschreiben von Feldern in OOP
 
1. würde ich mir überlegen, anstatt TList vielleicht TObjectList zu verwenden, dann hört die Pointerschieberei auf und die Typen sind etwas sicherer.

2. würde ich TItemList nicht mit TProduktList erweitern, sondern TProduktList von TTitemList ableiten. So sparst Du Dir die Eigenschaft Liste und kannst direkt darauf zugreifen.

3. TProdukt von TItem ableiten, so hat TProduct eine uid und kann bei der Suche nach selbigem benutzt werden.

Delphi-Quellcode:
function TItemListe.getPointerByUid(uid:Integer):TItem;
  var i:INteger;
  begin
  Result := nil;
  for i:=0 to Count-1 do
  if Items[i].uid=uid then
  begin
    Result:=Items[i];
    break;
  end;
  if Result = nil then
    raise ERangeError.Create('Kein ItemListeneintrag gefunden! '+#13+'UID: '+IntToStr(uid));
end;

rocedure TProdListe.add(bez:String; preis:Double; (...));
var i:Integer
begin
  Add(TProdukt.Create(bez, preis, (...)));
end;

mojo777 9. Mai 2007 23:25

Re: Überschreiben von Feldern in OOP
 
hi sh17,
habe nicht sofort antworten können. musste ein wenig rumexperimentieren.

habe ersteinmal deinen ersten tipp ausprobiert.
stoße dabei aber auf schwierigkeiten. :(

habe nun die Funktion
Delphi-Quellcode:
getPointerByUid(uid:Integer)
umgeschrieben und
der Rückgabewert ist nun
Delphi-Quellcode:
Result:=self.Liste.List[i-1];
wobei Liste:TobjectList
es wird auch ein Pointer zurückgegeben.
ich kann ihn aber nicht typisieren.

beim Aufruf
Delphi-Quellcode:
(...)
_prod:^TProdukt;
begin
_prod:=produkte.getPointerByUid(1);
showmessage(_prod.name);
end;
kommt ein access violation... :(
ich brauche aber unbedingt den pointer zu diesem objekt. sonst laufen die berechnungen alle durcheinander...


würde mich freuen, wenn du mir auch hier ein paar tipps geben könntest.
werde bald sobald ich ein bisschen zeit habe auch mal die anderen möglichkeiten genauer anschauen.

danke schon jetzt!

Gruß

EDIT:
hmmm.. habs glaub ich mit
Delphi-Quellcode:
function TItemListe.getPointerByUid(uid:Integer):Pointer;
  var i:INteger;
  erg:TItem;
  begin
  for i:=1 to self.Liste.Count do
    begin
    if (self.Liste.Items[i-1] as TItem).uid=uid then
      begin
      erg:=(self.Liste.Items[i-1] as TItem);
      Result:=@erg; // Items[i-1] as TItem);
      exit;
      end;
    end;
  //Result:=nil;
  raise ERangeError.Create('Kein ItemListeneintrag gefunden! '+#13+'UID: '+IntToStr(uid));
  end;
hinbekommen... muss ich aber etwas genauer testen ob ich mit dem pointer doch nicht auf kopierte instanzen zugreife....

xaromz 10. Mai 2007 08:16

Re: Überschreiben von Feldern in OOP
 
Hallo,
Zitat:

Zitat von mojo777
ich brauche aber unbedingt den pointer zu diesem objekt. sonst laufen die berechnungen alle durcheinander...

Bist Du Dir sicher, dass Du einen Pointer auf ein Objekt brauchst? Objekte sind doch schon Pointer.

Gruß
xaromz

mojo777 10. Mai 2007 17:46

Re: Überschreiben von Feldern in OOP
 
Zitat:

Objekte sind doch schon Pointer.
Hmmm.. hab mir auch gerade ein Objekt zurückgeben lassen...
hat eigentlich alles funktioniert...
nur irgendwie bin ich dennoch noch ein wenig unsicher....
bei meinen verketteten Listen hatte ich probleme mit rückgabe in form von ganzen Objekten...

die welt ist manchmal echt ein rätsel :-D

also in c++ wird definitiv eine kopie von (primitiven zumindest) werten zurückgegeben.. in java referenz.... ich blick da langsam nicht mehr so ganz druch... :(

hätte vielleicht jemand für mich einen link, wo ich die "grundlagen" von pascal nachlesen könnte?


danke

mkinzler 10. Mai 2007 17:48

Re: Überschreiben von Feldern in OOP
 
Objkete in Delphi sind Referenzen (also Zeiger). bei primitiven typen kommt es an, wie die Prozeduren/Funktionen deklariert sind.

Khabarakh 10. Mai 2007 18:05

Re: Überschreiben von Feldern in OOP
 
Zitat:

Zitat von mkinzler
Objkete in Delphi sind Referenzen (also Zeiger). bei primitiven typen kommt es an, wie die Prozeduren/Funktionen deklariert sind.

:gruebel: Bei Objektparametern kommt es genauso darauf an. Mit var oder out sind diese keine Referenzen auf Instanzen mehr, sondern Referenzen auf Referenz - ein ebenso wichtiger Unterschied wie bei Value-Types.

@mojo: Wertetypen sind grundsätzlich und sprachenunabhängig alle Typen, die auf dem Stack liegen (bei Referenztypen landet stattdessen nur die Adresse als Int auf dem Stack, die Daten liegen auf dem Heap). Bei Pascal wären das primitive Typen, Records, statische Arrays und Rücksprungadressen ^^; in einem speziellen, nicht gerade oft wichtigen Sinne auch Methodenzeiger . Strings sind zwar Referenzen, verhalten sich aber wie Wertetypen.

mojo777 10. Mai 2007 18:34

Re: Überschreiben von Feldern in OOP
 
Zitat:

Mit var oder out sind diese keine Referenzen auf Instanzen mehr, sondern Referenzen auf Referenz - ein ebenso wichtiger Unterschied wie bei Value-Types
ok. das bestätigt mein "empirisches" wissen :D

danke!
ich habs nun hinbekommen ohne viel code umschreiben zu müssen und dennoch eine elegante lösung zu benutzen!


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