Nein war definitiv nicht der Grund.
Delphi-Quellcode:
type
TMyClass = object(TObject)
definiert eben nicht den Typ eines neuen Objectes sondern eine Klasse von Objekten, aus Sicht der
OOP. Klasse deshalb weil es die Vorfahrklasse mit erstmal einer Unterklasse erweitert und diese Unterklasse TMyClass kann selber als Vorfahr für eine ganze Klassenhierarchie dienen. Nicht Objekte. Erst zur Laufzeit erzeugen wir diese Objekte, als Instanzen einer Klasse.
Nun gelten
OOP regeln nicht nur auf die fertigen Objekte, also Laufzeitobjekte, sondern schon bei der Typdefinition in der
OOP gelten auch die Regeln der
OOP. Um diesen Unterschied deutlich zu machen wurde syntaktisch durch Borland nachgebessert
Delphi-Quellcode:
type
TMyClass = class(TObject);
TMyClass ist eine abgeleitete Klasse von der Klasse TObjekt, und dies wird hier ganz klar auch im Source deutlich. Von TMyClass kann man, muß aber nicht, zur Laufzeit nun Objekte, also Instanzen erzeugen. Der Fakt das eine solche Typdeklaration einer Klasse auch abstrakt sein kann, quasi nur eine Klasse von der man niemals echte Laufzeitobjekte erzeugen wird, zb. TCustomControl etc. pp. in der
VCL, zeigt auch sehr deutlich das man die Regeln der
OOP auch, bzw. gerade besonders, bei den Typdeklarationen anwendet. Man deklaraiert also nicht mehr nur einen zb. type MyInteger = Integer, sondern man Deklariert ganze Strukturen von zueinander abhängigen und immer weiter verfeinerten Klassenhierarchien und schon während dieser Typdeklaration von Nachfahren kann der Compiler assistieren, Fehler prüfen usw. Mit dem class Bezeichner hat Borland die Sache nur syntaktisch sauberer gemacht.
Weiter gehts mit dem class of
Delphi-Quellcode:
type
TDECCipher = class(TDECObject)
end;
TCipher_AES = class(TDECipher);
TCipher_Blowfish = class(TDECCipher);
TDECCipherClass = class of TDECObject;
procedure MakeSomeThing(const ADECClass: TDECCipherClass);
var
Cipher: TDECCipher;
begin
Cipher := ADECClass.Create;
try
Cipher.BlaBla;
finally
Cipher.Free;
end;
end;
procedure Test;
begin
MakeSomeThing(TCipher_AES);
MakeSomeThing(TCipher_Blowfish);
end;
Man kann wie oben gezeigt eine Klasse auch als Variable/Parameter, eg. dynamisch zu Laufzeit benutzen. Man kann auch mit diesen Klassenvariablen, andere meinen sie als "Metaklassen" zu bezeichnen, so arbeiten das selbst die Übergabe von Klassen zur letzendlichen Erzeugung von Instanzen, gewissen
OOP Regeln unterliegen. zb. wird dies benutzt um die Polymorphie der Objektinstanzen auch auf die Klassenhierarchien auszudehenen. Erst dadurch werden zb. die DFMs Streams, also das
VCL Streaming System, überhaupt erst möglich.
All diese neuen Features hätte man auch in die, bzw. genauer um die, bestehenden alten Objekte bauen können und diese dann zu den heutigen Klassen ausbauen können. Genauergesagt hat dies Borland sogar exakt so gemacht. Die Klassenrecords im Codesegement, die also eine Klasse beschreiben, bestehen ab Offset 0 aus den gleichen Daten wie bei den alten Objekten. Vor dem Offset 0, also mit negativen Offsets stehen bei Klassen aber nun noch mehr Sachen. Borland hat also die alten Objekte aufgebohrt zu Klassen. Innerhalb der Klassenrecords wurde das neue Feature ->
RTTI -> auch noch angewendet, so das dieses ehemals nicht
OOP Feature heutzutage eben eine Grundlage der
OOP darstellt, um zb. neuere Möglichkeiten der Klassen, wie Properties usw. unterstützen zu können.
Im gleichen Atemzug hat Borland nun auch die Syntax geändert, was schlußendlich auch das Hauptziel war. Die Syntax mit den Klassen spiegelt einfach die
OOP besser und leichter verständlich wieder. Sie trennt zwei wichtige Aspekte der
OOP auch syntaktisch deutlich, die Deklaration von Typen der
OOP also einer Klassenhierarchie und deren Benutzung zur Laufzeit als Instanzen=Objekten dieser Klassenhierarchie. Der Bezeichner
object macht dies eben nicht deutlich, bzw. ist im Sinne der
OOP ein falscher Name für einen Bezeichner der eine Klassenhierarchie deklariert.
Mit dem Speichermanegement hat dies im Grunde nichts zu tuen. Man kann Instanzen zur Laufzeit beliebig allozieren, im Stack oder Hauptspeicher, ist egal. Man kann auch die Klassenrecords durch den Compiler an beliebiger Stelle abspeichern, muß also nicht wie in Delphi im Codesegment liegen, was aber sinnvoll ist. Eine Klasse lässt sich auch im Stack oder Heap dynamisch zusammenschustern zur Laufzeit. Diese Möglichkeit habe ich benutzt um zur Laufzeit aktiv das Verhalten einer Klasse, und damit all derer Instanzen, zu beeinflussen.
Gruß Hagen