Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#20

Re: Was ist ein Objekt ?

  Alt 29. Jul 2008, 10:45
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
  Mit Zitat antworten Zitat