Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - OOP - verschiedene Objekte in ein Array?
mtin - Mo 12.12.05 17:42
Titel: OOP - verschiedene Objekte in ein Array?
ich hab folgendes Problem, wir haben in der Schule jetzt mit der Objektorientierten Programmierung angefangen und da ein Beispiel in C++ bekommen...ich würde das ganze aber gerne in Delphi schreiben und habe nun Probleme alle Objekte (versch. Objekte -> ein array)
dies sind meine 3 Klassen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| type figurC = class x,y:integer; public procedure setXY(ortx,orty:integer); procedure getXY(var ortx:integer;var orty:integer); procedure show; end; quadratC = class(figurC) laenge:integer; public procedure setlaenge(l:integer); procedure show;virtual; end; circleC = class(figurC) radius:integer; public procedure setradius(r:integer); procedure show;virtual; end; |
hab also 2 figuren, quadratc und circlec...
(figurC wird nicht benötigt/gezeichnet, dient nur zur Vererbung von n paar dingen)
Diese wollte ich jetzt beide in einem dynamischen Array unterbringen, so dass ich z.b. um alle Kreise und Quadrate zu zeichnen nur eine for-Schleife brauch die von figuren[0] bis figuren[count(figuren)] figuren[i].show; macht...
Hab also versucht den ganzen Spaß zu schreiben, wie die anderen das in C++ gemacht haben:
figuren:array of figurC;
doch irgendwie geht das in Delphi nciht!!! In C++ konnten die einfach dann hinschreiben:
figuren[0] := QuadratC.Create;
soweit meckert Delphi auch noch nicht, allerdings kann ich jetzt in figuren[0].xxxxxx nicht auf die Quadratspeziefischen Funktionen zugreifen, was in C++ nun aber ging!!!!
mein Infoleherer meinte dann noch ich solle das quadrat erst in einer Variable vom typ QuadratC erstellen, und es erst am Ende mit
figuren[0]:= meinequadratvariable;
reinschreiben, aber das ging genausowenig, und außerdem würde ich ja gerne im Nachhinein auf einzelne Elemente des Arrays zugreifen und die jeweiligen speziefischen Einstellungen vornehmen, je nachdem ob da grad ein Kreis oder ein Quadrat an der Stelle gespeichert ist....
ich hoff ma das das einigermaßen verständlich is :D und das das mit delphi möglich is :?
MrSaint - Mo 12.12.05 17:47
Stichwort: SetLength! Du must in dem Array erst mal Speicher reservieren! ALternativ könntest du auch ein statisches Array machen, etwa so:
Delphi-Quelltext
1:
| variable: array [0..9] of figurC; |
MrSaint
Gausi - Mo 12.12.05 17:50
Ins Blaue geraten sollte das hinhauen:
Delphi-Quelltext
1:
| (figuren[0] as QuadratC).laenge; |
mtin - Mo 12.12.05 17:54
@MrSaint klar an sowas denkich schon ;)
@Gausi DAS KÖNNTE ES SEIN!!!! jetzt wo dus sagst MUSS es eigentlich so sein :D
ich probiers sofort aus!
EDIT:hm, so ganz geht das noch nicht!!
hier nochmal die Zuweisung, erstmal als extra Varialbe und dann erst in das array geschrieben:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| if RadioButton1.checked=true then begin meinQuadrat:=QuadratC.Create; meinQuadrat.setlaenge(strtoint(Edit3.text)); meinQuadrat.setXY(strtoint(Edit1.Text),strtoint(Edit2.Text)); ListBox1.Items.Add(IntToStr(length(figuren))+'. Quadrat');
figuren[length(figuren)-1]:=meinQuadrat;
end; if RadioButton2.checked=true then begin meinKreis:=circleC.Create; meinKreis.setradius(strtoint(Edit3.text)); meinKreis.setXY(strtoint(Edit1.Text),strtoint(Edit2.Text)); ListBox1.Items.Add(IntToStr(length(figuren))+'. Kreis');
figuren[length(figuren)-1]:=meinKreis; end |
doch wie zeige ich die jetzt alle an?
bei dem hier kommen leicht viele Fehlermeldungen:
Delphi-Quelltext
1: 2: 3: 4: 5:
| for i:=0 to (length(figuren)-1) do begin (figuren[i] as QuadratC).show; (figuren[i] as CircleC).show; end; |
aber das geht genausowenig (wird gar nix angezeigt)
Delphi-Quelltext
1: 2: 3: 4:
| for i:=0 to (length(figuren)-1) do begin figuren[i].show; end; |
Stefan.Buchholtz - Mo 12.12.05 18:37
Deine Prozedurdeklarationen sind falsch - Funktionen, die man überschreiben können soll, müssen in der Basisklasse mit
virtual deklariert werden und in abgeleiteten Klassen als
override. So ist es richtig:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| type Tfigur = class x,y:integer; public procedure setXY(ortx,orty:integer); procedure getXY(var ortx:integer;var orty:integer); procedure show; virtual; abstract; end; Tquadrat = class(Tfigur) laenge:integer; public procedure setlaenge(l:integer); procedure show;override; end; Tcircle = class(Tfigur) radius:integer; public procedure setradius(r:integer); procedure show; override; end; |
Der Aufruf von
Show geht dann mit
und es wird abhängig davon ob es nun ein TCircle oder TQuadrat ist das richtige Show aufgerufen. Ich habe
Tfigur.show noch als
abstract gekennzeichnet, das bedeutet, dass es in Tfigur keine Implementation davon gibt, sondern erst in abgeleiteten Klassen.
Zugriff auf nicht in der Basisklasse enthaltene Prozeduren funktioniert mit einem Cast:
Delphi-Quelltext
1:
| (figur[0] as Tquadrat).setlaenge(10); |
Das musst du so machen, weil SetLaenge in Tfigur nicht enthalten ist.
Delphi-Quelltext
1:
| figur[0].setlaenge(10); |
führt deswegen zu einem Compilerfehler. Das ist meines Wissens aber in C++ genauso.
In Delphi ist es übrigens Konvention, Klassennamen mit einem grossen T zu beginnen, deswegen habe ich das hier mal so gemacht.
Stefan
mtin - Mo 12.12.05 23:03
ok danke, das war schonmal sehr Hilfreich!
und...du glaubst es nich...es funktioniert :D
eine nächste frage wäre: wie finde ich heraus ob nun ein Kreis oder ein Quadrat in figuren[i] ist?
das einzige was mir dazu einfallen würde wäre das ausprobieren und mit try..except den Fehler abfangen...aber gibts da ne schönere Möglichkeit?
Stefan.Buchholtz - Di 13.12.05 11:13
mtin hat folgendes geschrieben: |
ok danke, das war schonmal sehr Hilfreich!
und...du glaubst es nich...es funktioniert :D
eine nächste frage wäre: wie finde ich heraus ob nun ein Kreis oder ein Quadrat in figuren[i] ist?
das einzige was mir dazu einfallen würde wäre das ausprobieren und mit try..except den Fehler abfangen...aber gibts da ne schönere Möglichkeit? |
Das kannst du mit dem is-Operator machen:
Delphi-Quelltext
1: 2: 3: 4:
| if figuren[i] is Tquadrat then begin Tquadrat(figuren[i]).setlaenge(10); ... |
Stefan
Stefan.Buchholtz - Di 13.12.05 11:22
Okay, aber da braucht man wieder extra Bibliotheken, weil Delphi (zumindest Delphi 7, Win32) nicht wirklich gut mit Collections ausgestattet ist. Java oder .NET sind da wesentlich besser gerüstet. Wir haben hier für interne Verwendung auch ein paar Collection-Klassen geschrieben.
Manchmal ist aber ein gutes altes Array auch die beste Lösung - wenn man weiss, wie viele Objekte man hat und nur über Index drauf zugreifen will, ist eine Collection-Klasse nur unnötiger Overhead.
Stefan
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!