Autor Beitrag
Brother John
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 28

WinXP
Turbo Delphi Explorer Win32
BeitragVerfasst: Do 01.12.05 03:02 
Hi, Delphi-Forum.

Seit einiger Zeit bin ich hier schon stiller Mitleser, aber jetzt brauche ich selber mal kompetente Hilfe.

Es geht um ein Win32-Programm (kein .NET). Ich versuche, zwecks einfachen Zugriffs verschiedene Kindklassen in ein Array zu packen. Die Klassendefinitionen sehen (ein etwas vereinfachtes Beispiel) so aus:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
  TAudioEncoder = class(TObject)
  end;
  
  TMP3 = class(TAudioEncoder)
  public
    Bitrate: Integer;
  end;
  
  TVorbis = class(TAudioEncoder)
  public
    Quality: Integer;
  end;


Dann instanziiere ich die Klassen in einer anderen Unit.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
var
  Encoder: array[1..2] of TAudioEncoder;
begin
  Encoder[1] := TMP3.Create;
  Encoder[2] := TVorbis.Create;


Das funktioniert auch soweit. Nur leider kann ich dann weder auf das Feld "Bitrate" noch auf "Quality" zugreifen: Fehler "undefinierter Bezeichner". Hab ich irgend etwas übersehen? Ich dachte, abgeleitete Klassen wären mit ihren Eltern kompatibel; so habe ich jedenfalls in der ObjectPascal-Referenz den Abschnitt über "Compatibility of class types" interpretiert.

Als Alternative geistert mir folgendes durch den Kopf: Die Klassenvariable is ja eigentlich nichts weiter als ein Zeiger. Könnte ich dann mein Array als "array[1..2] of Pointer" definieren und die Sache auf die Art lösen? Müsste ich dann in Sachen Speicherverwaltung was Zusätzliches (außer wie üblich Free sicherzustellen) beachten?

Thx schon mal für die Antworten.

_________________
Grüße
Brother John
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Do 01.12.05 03:20 
In dem array gibts Du ja nur Klassen vom Typ TAudioEncoder an und so werden sie dann auch angesprochen. Du musst also dann also beim Zugriff auf die Eigenschaften der Kindklassen (wenn Du diese so erzeugt hast, wie Du es gezeigt hast) einen Typecast machen:
ausblenden Delphi-Quelltext
1:
TMP3(Encoder[1]).Bitrate := 128;					
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Do 01.12.05 09:56 
Du kannst ein TMP3 oder TVorbis als TAudioEncoder behandeln, weil sie beide davon abgeleitet sind. Du kannst einen TAudioEncoder nicht ohne weiteres als TMP3 verwenden - es könnte ja auch ein TVorbis sein, der die Variable Bitrate gar nicht hat.
Du kannst mit is zur Laufzeit überprüfen, welchen Typ eine Variable hat und die weitere Verarbeitung davon abhängig machen, etwa so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
if Encoder[1] is TMP3 then
begin
  TMP3(Encoder[1]).Bitrate := x;
end
else if Encoder[1] is TVorbis then
begin
  ...
end;


Wenn du eine Typumwandlung wie TMP3(Encoder[1]) machst, sollstest du dir sicher sein, dass Encoder[1] auch wirklich ein TMP3 enthält. Wenn es ein TVorbis ist, kannst du schwer nachvollziehbare Laufzeitfehler wie Zugriffsverletzungen, unsinnige Daten und ähnliches kriegen. Eine andere Möglichkeit der Typumwandlung ist (Encoder[1] as TMP3). Das ist etwas langsamer, überprüft aber wie is, ob Encoder[1] wirklich ein TMP3 ist.

Stefan
Brother John Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 28

WinXP
Turbo Delphi Explorer Win32
BeitragVerfasst: Do 01.12.05 16:14 
Danke, Jungs. War ja eigentlich klar, dass das Problem war, dass ich mal wieder zu wenig computermäßig stur gedacht habe...

Nur leider macht die Typwandlung eben gerade den Vorteil zunichte, den ich mit dem Array erreichen wollte: nämlich einfach über den Index zugreifen zu können, ohne mich weiter im den Typ kümmern zu müssen.
Nochmal genau drüber nachgedacht ist mir allerdings aufgefallen, dass die Encoder ja so unterschiedlich sind, dass ich sowieso irgendwo vorher ein if, case, o.ä. drin haben muss. Und das macht die ganze Sache mit dem Array eigentlich unnötig.

Jedenfalls wieder was dazugelernt. :)

_________________
Grüße
Brother John