Autor Beitrag
Hein Blöd
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 51



BeitragVerfasst: Sa 03.04.04 14:49 
Ich hab mir 20000 Bücher und Faqs durchgelesen, aber ich blicke immer noch nicht bei inherited durch. Es wird irgendwie immer als selbstverständlich angesehen. Ich hab ein dickes Buch, so an die 1000 Seiten, das sich mit jedem Scheiß beschäftigt. Da werden die unwichtigsten Sachen deart in die Länge gezogen, daß man fast den Spaß am lesen verliert. Anscheinend wurde der Autor nach Seiten bezahlt, denn er ist in der Lage die einfachste Sache der Welt über zehn Seiten auszudehnen. Dann kam er irgendwann an inherited und handelte das mit zwei Sätzen ab. Eben das ist wichtig und das muß sein. Aber auch andere Bücher sind mir keine große Hilfe. Da wird irgendwie schon immer davon ausgegangen, daß man es bescheidweiß. Auch wenn es ein Anfängebuch ist.

Natürlich bleibt davon etwas kleben, aber es ist nicht so, und das ist jetzt sehr wichtig, daß es ohne zu überlegen nutzen könnte. Es ist nicht die Selbstverständlichkeit da mit der ich z.B. andere Dinge des Delphi behandele. Die Regel, daß inherited bei Constructor vorne und bei Dectructor hinten sein soll, die kenne ich. Aber warum? Ich weiß auch, daß inherited eine art Schlüssel ist mit der ich bei Klassenerstellung irgendwas mache. Aber es fehlt mit der Aha Effekt. Ich will Klassen erstellen, aber ohne das Verständnis von inherited werde ich es nicht so richtig kappieren. Wer kann mit den Aha Effekt verpassen?
raziel
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2453

Arch Linux
JS (WebStorm), C#, C++/CLI, C++ (VS2013)
BeitragVerfasst: Sa 03.04.04 15:24 
im prinzip wird durch inherited die funktion des vorgängers aufgerufen.
Wenn man also von TButton TMeinButton ableitet
ausblenden Delphi-Quelltext
1:
TMeinButton = class(TButton)					


wird durch das inherited hier
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
constructor TMeinButton.Create(AOwner: TComponent);
begin
  inherited create(AOwner);
  { eigener initialisierungscode }
end;

erst das Create von TButton abgearbeitet. So habs jedenfalls ich verstanden...
deswegen muss bei Destroy auch erst der eigene Code stehen und am Ende erst inherited.


raziel

_________________
JSXGraph
Andy DBase
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 42

win XP Home, win 98SE
D7 Prof
BeitragVerfasst: Sa 03.04.04 15:50 
mir hat ein Blick in's Wörterbuch geholfen, probier's doch auch mal... :)
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Sa 03.04.04 18:28 
to inherited heißt vererben - und genau das bewirkt inherited auch... durch inherited wird die entsprechende Methode der Basisklasse aufgerufen..

Der Sinn warum beim Konstruktor inherited als erstes, und beim Destruktor als letztes aufgerufen werden sollte ist einfach:
ein Aufruf von "inherited Create" sorgt dafür, dass der Konstruktor der Basis-Klasse aufgerufen wird. Das ist wichtig, da ja im Konstruktor diverse Felder initialisiert werden und eventuell benötigte Objekte erzeugt werden. Sofern man eines dieser Felder der Basis-Klasse in seinem eigenen Konstruktor braucht wäre es doch etwas blöd wenn es zu diesem Zeitpunkt noch nicht initialisiert wäre.. ;) Und beim Destruktor ist es eben genau umgekehrt..!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
raziel
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2453

Arch Linux
JS (WebStorm), C#, C++/CLI, C++ (VS2013)
BeitragVerfasst: Sa 03.04.04 19:11 
Motzi hat folgendes geschrieben:
to inherited heißt vererben

[klugscheiß]
1. to inherited gibts nicht. nur to inherit
2. es heißt erben, nicht vererben.
[/klugscheiß]
user defined image

_________________
JSXGraph
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: So 04.04.04 12:01 
raziel hat folgendes geschrieben:
1. to inherited gibts nicht. nur to inherit

Hoppla.. mein ich ja.. :oops:

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Hein Blöd Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 51



BeitragVerfasst: So 04.04.04 14:36 
Vielen Dank für die Hilfe, aber der Aha Effekt ist immer noch nicht da. Zwar ist die Bemerkung Inherited = Erben gut und sagt aus was damit gemeint ist, aber so 100%'ig weiss ich immer noch nicht wie das geht. Hier eine Frage die ich vor paar Wochen gestellt habe: www.delphiforum.de/viewtopic.php?p=129103

Hier die Kurzfassung. Auf die Frage ob das korrekt ist

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
constructor TListen.Create; 
begin 
  Liste1 := TStringList.Create; 
  Liste2 := TStringList.Create; 
  Liste3 := TStringList.Create; 
end

destructor TListen.Free; 
begin 
  Liste1.Free; 
  Liste2.Free; 
  Liste3.Free; 
end;


meinte KidPaddle, dass das besser ist

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
constructor TListen.Create;  
begin  
  inherited Create; 

  fListe1 := TStringList.Create;  
  fListe2 := TStringList.Create;  
  fListe3 := TStringList.Create;  
end;  

destructor TListen.Destroy; 
begin  
  FreeAndNil(fListe1);  
  FreeAndNil(fListe2);  
  FreeAndNil(fListe3);  

  inherited Destroy; 
end;


Ignorieren wir mal FreeAndNil und die etwas andere Variablenamen, aber warum ist es besser hier inherited zu nehmen. Es funktioniert auch ohne.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: So 04.04.04 14:45 
Zwei Sachen...

1) Free ist kein Destruktor sondern nur eine Methode die folgendermaßen ausschaut:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

Free ruft also intern Destroy auf falls der Self-Pointer ungleich nil ist.
Deswegen überschreibt man auch immer Destroy und nicht Free..!

2) inherited ruft man immer auf, damit auch die Methode der Basisklasse ausgeführt wird. Gerade beim Konstruktor als auch beim Destruktor ist das besonders wichtig, damit auch die Basisklasse diverse Initialisierungen und Aufräumarbeiten durchführen kann.
Nachdem deine Klasse aber von TObject abgeleitet ist ist es egal ob du inherited aufrufst, da sowohl der Konstruktor Create als auch der Destruktor Destroy von TObject eigentlich nur eine Dummy-Dasein fristen, da sie beide einen leeren Funktions-Rumpf haben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
constructor TObject.Create;
begin
end;

destructor TObject.Destroy;
begin
end;

In (fast) allen anderen Fällen ist es aber äußerst wichtig inherited aufzurufen..!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Phantom1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 390



BeitragVerfasst: So 04.04.04 14:58 
Schau dir mal folgendes Beispiel genau an:

ausblenden volle Höhe Delphi-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:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
type  
  TBasisObj = class(TObject)  
   public  
     constructor Create;  
     destructor Destroy; override
  end;  

  TNeuObj = class(TBasisObj)  
   public  
     constructor Create;  
     destructor Destroy; override
  end;  

{ TBasisObj }

constructor TBasisObj.Create;  
begin  
  inherited Create; // ruft TObject.Create auf
  // ...
end;  

destructor TBasisObj.Destroy; 
begin  
  // ...
  inherited Destroy; // ruft TObject.Destroy auf
end;

{ TNeuObj }

constructor TNeuObj.Create;  
begin  
  inherited Create; // ruft TBasisObj.Create auf
  // ...
end;  

destructor TNeuObj.Destroy; 
begin  
  // ...
  inherited Destroy; // ruft TBasisObj.Destroy auf
end;


Man kann im übrigen wirklich den Aufruf von Inherited bei einer direkt von TObject-Abgeleiteten klasse weglassen, weil der Constructor und Destructor in der TObject-Klasse leer ist. Man sollte es aber trotzdem machen, wegen der übersichtlichkeit und evtl verwirrung ^^
KidPaddle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 351

WinXP,Linux
D7 Prof, XE7
BeitragVerfasst: So 04.04.04 15:10 
Die Bedeutung von inherited ist schon erklärt worden. Jedes Objekt kapselt Daten, die es für die Verabreitung in irgendeiner Art und Weise benötigt. Wenn Du ein Basisobjekt hast, welches ein Array verwaltet, dann wird dieses Array z. B. im Constructor erstellt und im Destructor wieder freigegeben. Weitere Methoden des Objektes greifen auf das im Constructor reservierte Array zu. Diese erwarten, das das Array richtig initialisiert wurde.

Du leitest ein neues Objekt von dem Basisobjekt ab. Wenn Du nicht den Constructor des Vorgänger mit inherited aufrufst, dann wird das Array nicht reserviert und die Mehtoden, die dieses Array manipulieren, erzeugen Speicherzugriffsfehler. Machst Du den Aufruf nicht im Destructor, bleibt ein Memory Leak, das heist, nicht freigegebener Speicher, übrig und das kann zum Absturz der Anwendung oder mehr führen, wenn dieses Objekt sehr häufig verwendet wird. Normalerweise gibt Delphi den Speicher beim beenden des Programmes frei, aber halt erst beim beenden und nicht während des laufenden Programmes.

Dein Objekt wurde direkt von TObjekt abgeleitet. Der Constructor und Destructor von TObjekt ist aber leer und daher gibt es beim weglassen von inherited keine Probleme. Das ist aber eine Ausnahme, wenn man mit Objekten arbeitet. Damit man nicht immer wieder an die Ausnahmen denken muss, wenn man den Quelltext sich ansieht, setzt man den Aufruf einfach rein, schaden tut er nicht und man gewöhnt sich gleich an, den Aufruf den Constructor/Destructors nicht zu vergessen.

Ich hoffe, ich konnte es Dir verdeutlichen.

Gruß
KidPaddle
Hein Blöd Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 51



BeitragVerfasst: Sa 03.07.04 18:17 
Ich versuche mich noch mal mit den Thema und bringe es wieder nach vorne.

Ich hab alle Hinweise beachtet und unendlich viele Beispiele gemacht. Aber egal was ich mache, nie kriege ich Probleme wenn ich inherited weglasse. Ich hab Klassen erstellt, die abgeleitet wurden. Die hab ich wieder abgeleitet und wieder. Zwischendurch hab ich Objekte initialisiert und in der abgeleietetn Klasse angewendet. Nie hatte ich Probleme es ohne inherited zu machen. Vielleicht ist das Ganze nicht so kompliziert wie ich mir das vorstelle. Aber jedes mal wenn ich glaube es verstanden zu haben kommt etwas was mich wieder durcheinanderbringt.

Ich gehöre leider zu den Leuten die nicht weiter machen können wenn sie ein Problem haben. Zur Zeit verstehe ich die Sache mit inherited nicht. Daraus follgt, daß das ganze Klassen Thema liegen lasse. Ich kann einfach nicht etwas hinnehmen. Vielleicht kann einer mir ein Beispiel fabrizieren das wirklich knallt, wenn ich kein inherited nehme. Irgendwie hab ich den Aha Effekt nicht und egal was ich machen er kommt nicht. Ich könnte einfach inherited einbauen, aber wenn ich es nicht verstehe, dann wiederstrebt es in mir es zu machen.

Ich will nicht beachaupten, daß ich das was bisher geschrieben wurde nicht verstanden habe, aber ein *ach so ist das* kommt nicht zu stande.

Ich verstehe, daß meine Klasse die Eigenschaften der alten klasse erbt. Aber egal was für ein Beispiel ich gemacht habe, es klappte auch ohne inherited.
mstuebner
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 132

Win2000, XP
D7
BeitragVerfasst: Sa 03.07.04 19:35 
Hein Blöd hat folgendes geschrieben:
Zur Zeit verstehe ich die Sache mit inherited nicht.

Ich befürchte, dass man es nicht noch besser und einfacher beschreiben kann, als dies bereits geschehen ist.

Hein Blöd hat folgendes geschrieben:
Vielleicht kann einer mir ein Beispiel fabrizieren das wirklich knallt, wenn ich kein inherited nehme.

Dann lies den Thread noch einmal. Genau diese Beispiele sind hier aufgezeigt. Wenn auch schon in jedem Beitrag geschrieben, wenn ohne inherited wird die gleichnamige Methode der Vorgängerklasse nicht aufgerufen und dadurch evtl. Initialisierungen nicht durchgeführt. Nicht mehr, nicht weniger, nichts anderes.

Hein Blöd hat folgendes geschrieben:
Ich will nicht beachaupten, daß ich das was bisher geschrieben wurde nicht verstanden habe, aber ein *ach so ist das* kommt nicht zu stande.

Kannst Du mal ein Beispiel geben WANN es bei Dir "aha so ist das" macht?

_________________
mfg Matthias
dmx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19

Gentoo Linux, Win XP Pro
D6 Prof, K3 Open, Freepascal
BeitragVerfasst: Sa 03.07.04 21:41 
hallo zusammen,

okay, dann versuch ich auch mal es zu erklären. vielleicht mal ein beispiel, das nichts mit konstruktoren und destruktoren zu tun hat.

etwas verallgemeinert gesprochen hilft inherited vor allem dann, wenn wir keine konkreten gegenstände in klassen abstrahiert abbilden, sondern stattdessen, wenn wir abläufe oder vorgänge "objektivieren". soviel nur zur theorie der objektorientieren programmierung.

stellen wir uns einfach mal vor, wir wollen eine kleine klassenhierachie erstellen, um einen kauf abzubilden.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
TVorgang = class
 public
  procedure Ausführen; virtual;
end;

TKaufVorgang = class(TVorgang)
 public
  procedure Ausführen; override;
end;


virtual in der ersten klasse macht diese procedure grob gesprochen überladbar. dh. in jedem nachfolger (KaufVorgang) kann eine procedure genauso heißen, nur muss dann in diesem nachfahren (TKaufVorgang) noch das schlüsselwort override angegeben werden.
implementieren wir nun:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TVorgang.Ausführen;
begin
  FasseEntschluss;
  BereiteAllesVor;
end;


um einen vorgang abschließen zu können benötogen wir logischerweise erst mal den entschluss und müssen dann alles vorbereiten.
wenn wir nun etwas konkreter werden und einen nachfahren von TVorgang implementieren, zb. TKaufVorgang, dann schaut des erstmal so aus:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TKaufVorgang.Ausführen;
begin
  Kaufe;
end;


nun, das ist eigentlich klar. aber der vorgang ist so noch nicht komplett, denn auch zum kaufen gehören ja schließlich der entschluss und die vorbereitung (mehr oder weniger). klar, wir könnten hingehen und folgendes machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TKaufVorgang.Ausführen;
begin
  FasseEntschluss;
  BereiteAllesVor;
  Kaufe;
end;


aber was wäre wenn das nicht nur zwei prozeduren wären, sondern 200 zeilen code die zu TVorgang allein gehören? es ginge auch, aber dann wäre das ganze sehr unübersichtlich (copy&paste-verallgemeinerung). schön wäre es jetzt natürlich wenn wir einfach auf die procedure aus dem vorgänger zugreifen könnten. etwas so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TKaufVorgang.Ausführen;
begin
  inherited Ausführen; //FasseEntschluss; BereiteAllesVor;
  Kaufe;
end;


inherited Ausführen; entspricht also TVorgang.Ausführen. hier wird einfach nur der code aus dem vorgänger in die prozedur geholt, was einem eine menge schreibarbeit ersparen kann.

alles was nun mit kon-/destruktoren und inherited zu tun hat, wurde ja schon beschrieben, vielleicht verstehst du es jetzt?

hoffe sehr, vielleicht ein wenig geholfen haben zu können.

gruß, dmx.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: So 04.07.04 14:45 
Ein Beispiel wo es ohne inherited knallt..? Kein Problem..!
ausblenden volle Höhe Delphi-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:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Menus, ComCtrls, ToolWin, Math;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TDummyClass = class
      FMessage: String;
    public
      procedure ShowTestMessage;
  end;

  TBaseClass = class
    private
      FDummyClass: TDummyClass;
    public
      property DummyClassProperty: TDummyClass read FDummyClass;
      constructor Create; virtual;
      destructor Destroy; override;
  end;

  TMyClass1 = class(TBaseClass)
    public
      constructor Create; override;
  end;

  TMyClass2 = class(TBaseClass)
    public
      constructor Create; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TDummyClass }

procedure TDummyClass.ShowTestMessage;
begin
  ShowMessage(FMessage);
end;

{ TMyClass }

constructor TBaseClass.Create;
begin
  inherited;
  FDummyClass := TDummyClass.Create;
  FDummyClass.FMessage := 'Test-Message from TDummyClass-Instance';
end;

destructor TBaseClass.Destroy;
begin
  FDummyClass.Free;
  inherited;
end;

{ TMyClass1 }

constructor TMyClass1.Create;
begin
  inherited;
  ShowMessage('Constructor of TMyClass1 - uses inherited');
  DummyClassProperty.ShowTestMessage;
end;

{ TMyClass2 }

constructor TMyClass2.Create;
begin
  ShowMessage('Constructor of TMyClass2 - doesn''t use inherited');
  DummyClassProperty.ShowTestMessage;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  with TMyClass1.Create do
    Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  with TMyClass2.Create do
    Free;
end;

end.

Wie man sieht, einfach eine Form mit 2 Buttons und den Code reinkopiern.. dann siehst du was passieren kann..! ;)

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.04 18:57 
Klassen Tutorial: tutorials.luckie-online.de