Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Klassenverständnis Problem


Fingolfin - So 09.03.03 16:04
Titel: Klassenverständnis Problem
Hier mein erster Post und gleich 'ne Frage :oops:

Hallöle, ich habe ein Problem (wahrscheinlich allgemeines Verständnis) bei Klassen mit Delphi.

Ich habe das ganze mal ins Tierreich abstrahiert, um es leichter verständlich zu machen.

Ich habe jetzt also ne Klasse Katze, Tier und Hund, wobei Katze und Hund von Tier erben.



Quelltext
1:
2:
3:
4:
5:
var 
Tier:TTier; 
begin 
Tier:=TKatze.Create; //funktioniert 
end;


Jetzt wollte ich eine Klasse Tieransammlung kreieren und dabei auf ObjectLists verzichten (Delphi 4).



Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
TTierAnsammlung=class 
private 
FTiere:Array of TTier; 
function GetTier(ind:Integer):TTier; 
procedure SetTier(ind:Integer;tier_:TTier); 
public 
property Tiere[ind:Integer]:TTier read GetTier write SetTier; 
end; 

implementation 

function TTieransammlung.GetTier(ind:Integer); 
begin 
if Length(FTiere)>ind then 
Result:=FTier[ind] 
else 
begin 
Result:=nil; 
end; 
end; 

procedure TTieransammlung.SetTier(ind:Integer;tier_:TTier); 
begin 
if ind<Length(FTiere) then 
begin 
SetLength(FTiere,ind+1); 
FTiere[ind]:=TTier.Create; 
end; 
end;


Jetzt funktioniert folgendes nicht:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
var 
tieransammlung:TTieransammlung; 
begin 
tieransammlung.Tiere[0]:=TKatze.Create; 
//bis hierhin sagt er nix 

ShowMessage(tieransammlung.Tiere[0].Classname); 

{gibt TTieransammlung aus, hier sollte doch aber TKatze ausgegeben werden  :?  Demzufolge komme ich auch nicht an die Eigenschaften von TKatze ran} 

//Selbst: 

(Tieransammlung.Tier[0] as TKatze).beine:=5; 

//liefert mit einen Invalid Class Typecast 

end;


Vielleicht wißt ihr ja, was ich hier falsch mache.
(Meine Abschlußprüfung rückt in schreckliche Nähe :( )

Danke euch schonmal.

Fingolfin

Moderiert von user profile iconKlabautermann: Code-Tags hinzugefügt.


maximus - So 09.03.03 16:24

Hi, nicht persöhnlich nehmen...aber erstma Schelte wegen der formatierung: BITTE MACH CODE-TAGS UM DEN CODE UND FORMATIERE IHN...erhöht die wahrscheinlichkeit auf antworten.

So.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TTieransammlung.SetTier(ind:Integer;tier_:TTier); 
begin 
if ind<Length(FTiere) then 
begin 
SetLength(FTiere,ind+1); 
FTiere[ind]:=TTier.Create; 
end; 
end;


Ich denke du meinst hier 'grösser gleich':


Quelltext
1:
if ind>=Length(FTiere) then                    


hilft das?


maximus - So 09.03.03 16:30

Achja..hab die frage nicht zu ende gelesen...ist auch echt aunstrengend :D

dein code(Tieransammlung.Tier[0] as TKatze).beine:=5;

würd ich mal so schreibenTKatze(Tieransammlung.Tier[0]).beine:=5;

hilft das ?


maximus - So 09.03.03 16:36

Nochwas :roll: :

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TTieransammlung.SetTier(ind:Integer;tier_:TTier); 
begin 
if ind<Length(FTiere) then 
begin 
SetLength(FTiere,ind+1); 
FTiere[ind]:=TTier.Create; 
end; 
end;


Wenn 'tier_' schon created ist, dann musst du die referenz in dem array nicht instanzieren, sondern einfach zuweisen. Oder auf nil abfragen und dann createn:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TTieransammlung.SetTier(ind:Integer;tier_:TTier); 
begin 
  if ind>=Length(FTiere) then 
  begin 
    SetLength(FTiere,ind+1); 
    if tier_ = nil then tier_ := TTier.Create
    FTiere[ind]:= tier_; 
  end; 
end;


?


derDoc - So 09.03.03 17:57

Versuch es doch mal mir ClassType


AndyB - So 09.03.03 18:59

maximus hat folgendes geschrieben:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TTieransammlung.SetTier(ind:Integer;tier_:TTier); 
begin 
  if ind>=Length(FTiere) then 
  begin 
    SetLength(FTiere,ind+1); 
    if tier_ = nil then tier_ := TTier.Create
    FTiere[ind]:= tier_; 
  end; 
end;

Und was passiert hier, wenn ind < Length(FTiere) ist?


maximus - Mo 10.03.03 00:59

@Andyb:
Na, nix *g* man kann ja nicht alles vorkauen. Der code war halt noch nicht formatiert...find ich schon unglaublich gut von mir, dass ich das entziffern konnte :wink:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TTieransammlung.SetTier(ind:Integer;tier_:TTier); 
begin 
  if ind>=Length(FTiere) then 
  begin 
    SetLength(FTiere,ind+1); 
    if tier_ = nil then tier_ := TTier.Create 
    FTiere[ind]:= tier_; 
  end 
  else FTiere[ind]:= tier_; // hätt ich ihm auch selbst zugetraut
end;


bis denn. funzt et :?:

PS: Vielleicht noch auf ind < 0 abfragen.


Fingolfin - Mo 10.03.03 10:05

Ja es funktioniert wunderbar. Vielen Dank für die Mühe, obwohl mir nicht 100% klar ist, wo der Unterschied liegt. Ob ich TTier jetzt extra kreiere und dann zuweise oder sofort kreiere, wie ich's vorher gemacht habe. :?:

Vielen Dank.

Und sorry wegen der Codeformatierung, ich wußte echt nicht, daß sowas geht. :oops:

Ich werd mich bessern, versprochen. :)

Fingolfin


maximus - Mo 10.03.03 11:55

Naja...mit dem create: Wenn du...tieransammlung.Tiere[0]:=TKatze.Create;
...machst hast du ja schon eine instanz erstellt, die du in die liste einglidern willst. Wenn du nun in der procedure noch mal create machst, dann hast du zwei instanzen. Einmal von TKatze und einmal von TTier, wobei du dann nur die referenz auf TTier gespeichert hättest. Dh. du hättest ein SpeicherLeck, da du keine gültige Referenz auf die Instanz von TKatze hättest und das war wohl nicht dein ziel.

IMHO würd ich das create in der prozedure weg lassen, du musst dann aber immer auf NIL prüfen.

Bis denn.


Fingolfin - Mo 10.03.03 17:55

Alles klar, jetzt hab ich's soweit verstanden :D

Ist mein erster Versuch mit Klassen in Delphi, da hab' ich einiges an Nachholbedarf.

Noch eine blöde Frage:

Wo ist der Unterschied zwischen:


Quelltext
1:
(Tieransammlung.Tier[0] as TKatze).beine:=5;                    


und


Quelltext
1:
TKatze(Tieransammlung.Tier[0]).beine:=5;                    


Ist doch eigentlich beides nur 'ne Typumwandlung oder?

(Jetzt hab ich's auch mit den Code-Tags kapiert. Sehr nützlich!)

Fingolfin