Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Versuche Objektorientierung zu lernen (https://www.delphipraxis.net/166561-versuche-objektorientierung-zu-lernen.html)

foerster7892 18. Feb 2012 19:23

Delphi-Version: 5

Versuche Objektorientierung zu lernen
 
Hi,

ich hab jetzt verschiedene Tutorials gelesen und verstehe meine Fehler trotzdem nicht könntet ihr mir vllt helfen?

unit 1:
Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  Rechnen:TRechnen;
implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  Rechnen:=TAddition.create;
  Label1.caption:=FlaotToStr(Rechnen.calcit(StrToFloat(Edit1.Text), StrToFloat(Edit2.Text)));
  Rechnen.Destroy;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Rechnen:=TSubtraktion.create;
  Label1.caption:=FloatToStr(Rechnen.calcit(StrToFloat(Edit1.Text), StrToFloat(Edit2.Text)));
  Rechnen.Destroy;
end;

end.
unit2:
Delphi-Quellcode:
unit Unit2;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type
  TRechnen=class(TObject)
    public
      constructor create;
      function calcit(a,b:real):real;virtual;
  end;

  TAddition=class(TRechnen);
    public
      constructor create;
      function calcit(a,b:real):real;override;
  end;

  TSubtraktion=class(TRechnen);
    public
      constructor create;
      function calcit(a,b:real):real;override;
  end;

var calcs:TRechnen;
implementation


  function TAddition.calcit(a,b:real):real;
  begin

    result:=a+b;
  end;

  function TSubtraktion.calcit(a,b:real):real;
  begin
    result:=a-b;
  end;

end.
Ja die Fehlermeldung ist denke ich egal(da sie auch nichts hilfreiches aussagt)

Ich möchte halt 2 Zahlen eingeben und dann als Ergebnis entweder den Summanden oder die Differenz bekommen. Das alles mit einer Klasse TRechnen welche weitervererbt wird an die Klassen TAddition und TSubtraktion.

Ich hoffe ihr könnt mir dies erklären.

Außerdem würde ich mich freuen wenn mir jemand nocheinmal mit eigenen Worten den Sinn von inhirated und die genaue Funktionsweise des constructors erklären könnte. (Den constructor braucht man irgendwie um Speicher für die klasse zu reservieren und sie zu erstellen, was bedeutet dies genau? Und inherited ka wird halt manchmal auch hingeschrieben und manchmal nicht...)

PS.: Ich benutze Lazarus falls es da irgendetwas spezielles zu beachten gibt.

implementation 18. Feb 2012 19:38

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von foerster7892 (Beitrag 1151758)
Ja die Fehlermeldung ist denke ich egal(da sie auch nichts hilfreiches aussagt)

Oh doch, sie sagt eine Menge aus. Lass mich raten: Der Compiler findet die Implementierung von TRechnen.calcit nicht? Und alle drei Konstruktoren auch nicht?
Die Glaskugel sagt "Forward declaration not solved: ....".

Zitat:

Außerdem würde ich mich freuen wenn mir jemand nocheinmal mit eigenen Worten den Sinn von inhirated und die genaue Funktionsweise des constructors erklären könnte. (Den constructor braucht man irgendwie um Speicher für die klasse zu reservieren und sie zu erstellen, was bedeutet dies genau? Und inherited ka wird halt manchmal auch hingeschrieben und manchmal nicht...)
Delphi-Quellcode:
inherited
bedeutet, dass die gleichnamige Methode der Elternklasse aufgerufen wird. Man kann hinter das
Delphi-Quellcode:
inherited
auch noch den Methodennamen und die Parameterliste schreiben, falls sich eines von beiden von der aktuellen Methode unterscheidet.

Zum Konstruktor: Es gibt im Speicher einen bestimmten Bereich, der sich "Heap" nennt. Alle Klasseninstanzen werden dort erstellt. Der Heapspeicher ist aber nicht sofort für die Anwendung verfügbar, sondern er muss ihr erst vom Betriebssystem zugewiesen werden. Auf unterster Ebene geht das mit malloc() und realloc(), aber das ist eine ganz schöne Frickelei. Der Konstruktor nimmt dir das ein bisschen ab und besorgt den Speicher für dich. Das tut er schon in der Basisklasse TObject, also wenn du immer brav
Delphi-Quellcode:
inherited
benutzt*, musst du dich darum nicht groß kümmern und kannst den Konstruktor allein dafür benutzen, die Felder zu initialisieren.

Zitat:

PS.: Ich benutze Lazarus falls es da irgendetwas spezielles zu beachten gibt.
In der Hinsicht eigentlich nicht. Es gibt ein paar Dialektunterschiede, aber die liegen woanders. Und die Fehlermeldungen lauten eben etwas anders als bei Delphi.


Oh und noch was: In Unit1 rufst du Rechnen.Destroy direkt auf. Tu das nicht! Jetzt im Moment geht das vielleicht noch gut, aber wenn die Programme mal komplexer werden, kann das schon eine potentielle Fehlerquelle werden. Nimm stattdessen Rechnen.Free!



*) Bei Konstruktor und Destruktor werden sie auch automatisch ergänzt, wenn sie fehlen, von daher nicht allzu schlimm, wenn man sie dort vergisst.

foerster7892 18. Feb 2012 19:51

AW: Versuche Objektorientierung zu lernen
 
zur Fehlermeldung:
nein sie sagt: Unit2.pas(19,7) Fatal: Syntax error, "=" expected but "CONSTRUCTOR" found

So danke für die kurze Erklärung.

Nur nochmal zum Verständnis:
Wenn ich inherited benutze dann greife ich auf die Funktion der Mutterklasse zu also:

constructor TAddtion.create;
begin
inherited;
end;

jetzt würde ich also wenn ich:

Rechnen:=TAddition.create;
Rechnen.calcit(a,b);

und dies würde bei mir dann in der Mutterklasse landen und somit würde nichts passieren da diese ja in meinem Bsp. leer ist.

...und warum soll ich destroy nicht verwenden, in versch. Tutorials wurde Destroy verwendet in anderen free. Where is the difference?

...und wann muss ich überhaupt constructor create; schreiben und wann nicht und wo muss ich dass jeweils einfügen?

implementation 18. Feb 2012 19:58

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von foerster7892 (Beitrag 1151761)
zur Fehlermeldung:
nein sie sagt: Unit2.pas(19,7) Fatal: Syntax error, "=" expected but "CONSTRUCTOR" found

Das kommt daher, dass du hinter
Delphi-Quellcode:
class(TRechnen)
beide Male ein Semikolon hast. Das heißt für den Compiler: "Hier ist der Typ zuende" - und daraufhin liest er 'public' und denkt, du willst noch einen weiteren Typen namens "public" deklarieren. Nimm die Semikola mal weg.

Sir Rufo 18. Feb 2012 20:04

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von implementation (Beitrag 1151763)
Zitat:

Zitat von foerster7892 (Beitrag 1151761)
zur Fehlermeldung:
nein sie sagt: Unit2.pas(19,7) Fatal: Syntax error, "=" expected but "CONSTRUCTOR" found

Das kommt daher, dass du hinter
Delphi-Quellcode:
class(TAddition)
und
Delphi-Quellcode:
class(TSubtraktion)
Semikola hast. Das heißt für den Compiler: "Hier ist der Typ zuende" - und daraufhin liest er 'public' und denkt, du willst noch einen weiteren Typen namens "public" deklarieren. Nimm die Semikola mal weg.

Du meinst
Delphi-Quellcode:
TAddition=class(TRechnen); // <- das da
und
Delphi-Quellcode:
TSubtraktion=class(TRechnen); // <- das da
Des Weiteren finde ich noch
Delphi-Quellcode:
  Label1.caption :=
    FlaotToStr( // das heißt FloatToStr :o)
      Rechnen.calcit( 
        // 1. Parameter
        StrToFloat( // erwartet genau 1 Str-Parameter
          Edit1.Text,
          Edit2.Text // wozu also der 2. Parameter hier ???
        )
        // 2. Parameter ... wo ist der ???
      )
    );
Aus diesen Gründen kommen bei mir auch immer sehr viele Leerzeichen in den Code - auch wenn der Styleguide diese verpönt - denn m.E. sieht man dann viel eher, dass da was nicht passt
Delphi-Quellcode:
...
Label1.Caption:=FloatToStr(Rechnen.CalcIt(StrToFloat(Edit1.Text, Edit2.Text)));
...
Label1.Caption := FloatToStr( Rechnen.CalcIt( StrToFloat( Edit1.Text, Edit2.Text ) ) );
...

implementation 18. Feb 2012 20:11

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1151764)
Du meinst
Delphi-Quellcode:
TAddition=class(TRechnen); // <- das da
und
Delphi-Quellcode:
TSubtraktion=class(TRechnen); // <- das da

Genau, danke für den Hinweis, ist korrigiert :thumb:

himitsu 18. Feb 2012 20:34

AW: Versuche Objektorientierung zu lernen
 
Ist public denn nicht ein "reserviertes Wort"?

So wie es aussieht, wird es (nach dem ; ) dennoch als Typenbezeichner erkannt und deswegen wird danach auch das = erwartet. :gruebel:

implementation 18. Feb 2012 20:39

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von himitsu (Beitrag 1151770)
Ist public denn nicht ein "reserviertes Wort"?

Es gibt Schlüsselwörter, die sind nur in einem bestimmten Kontext reserviert. Wie ja bspw. auch
Delphi-Quellcode:
read
und
Delphi-Quellcode:
write
.
Public kann gut eines davon sein, denn wo braucht man Public auch sonst außer in Klassen- und Nostalgie-Object-Deklarationen?

Sir Rufo 18. Feb 2012 20:40

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von himitsu (Beitrag 1151770)
Ist public denn nicht ein "reserviertes Wort"?

So wie es aussieht, wird es (nach dem ; ) als Typenbezeichner erkannt und deswegen wird danach auch das = erwartet. :gruebel:

Ich denke das ist nur so ein "halb reserviertes" Wort, denn
Delphi-Quellcode:
public
macht ja nur Sinn im Kontext einer Typ-Deklaration, und die ist ja durch das ; schon abgeschlossen. Darum kann der Compiler das eben nicht richtig einsortieren ;)

EDIT: zu langsam ... na gut

foerster7892 18. Feb 2012 20:42

AW: Versuche Objektorientierung zu lernen
 
hi,
ja dass mit der Parameterübergabe bei den Funktionen war nen Tippfehler.

ich hatte oben die Antwort noch editiert wie ich ergänzt hatte, da ihr so schnell geantwortet habt würde ich mich nun noch über Antworten auf die obigen Fragen freuen.

Außerdem geht es leider noch nicht wenn ich den Fehler mit StrToFloat behoben habe, da dann der vorhergesagte Fehler auftritt.(Forward declaration not solved... was bedeutet dass wie behebe ich es?)

Public ist reserviert und bedeutet soweit ich weiß dass die Methoden die unter Public definiert werden öffentlich sind und somit auch aus anderen Units/Klassen gesehen werden können und ich darauf zugreifen kann.



PS:
"Btw. "free" würde ich in Ruhe lassen. Überschreibe lieber Destroy." habe ich in anderen Foren gefunden?

himitsu 18. Feb 2012 20:47

AW: Versuche Objektorientierung zu lernen
 
Free heißt immer Free.

In Lazarus kann der Destructor und der Constructor auch anders heißen.
Und schon hast du ein Problem, mit dem Verwenden von Destroy.

Sir Rufo 18. Feb 2012 20:49

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von foerster7892 (Beitrag 1151773)
"Btw. "free" würde ich in Ruhe lassen. Überschreibe lieber Destroy." habe ich in anderen Foren gefunden?

Dann hast du da was falsch verstanden.

Eine Instanz wird mit
Delphi-Quellcode:
Foo := TFoo.Create;
// something with Foo
Foo.Free;
ins Nirwana befördert.

Will man bei der Zerstörung der Klasse etwas spezielles ausführen, dann wir der Destructor überschrieben und der heißt nun mal
Delphi-Quellcode:
Destroy
.

Also man benutzt
Delphi-Quellcode:
Free
und überschreibt
Delphi-Quellcode:
Destroy
!

Sir Rufo 18. Feb 2012 21:03

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von foerster7892 (Beitrag 1151758)
Außerdem würde ich mich freuen wenn mir jemand nocheinmal mit eigenen Worten den Sinn von inhirated und die genaue Funktionsweise des constructors erklären könnte. (Den constructor braucht man irgendwie um Speicher für die klasse zu reservieren und sie zu erstellen, was bedeutet dies genau? Und inherited ka wird halt manchmal auch hingeschrieben und manchmal nicht...)

Jedes Objekt (TObject) hat von Haus aus einen
Delphi-Quellcode:
constructor
.
Dieser reserviert automatisch den Speicher.

Wenn du keine weiteren Anforderungen an dein Objekt hast, dann brauchst du auch keinen speziellen
Delphi-Quellcode:
constructor
.

Delphi-Quellcode:
type
  TFoo = class
    public
      procedure DoSomething;
  end;

...

procedure TFoo.DoSomething;
begin
  // some code
end;
Allerdings musst du alles, was du in der Typ-Deklaration angibst auch ausformulieren (Ausnahme bei
Delphi-Quellcode:
virtual abstract
)

Delphi-Quellcode:
inherited
bedeutet, dass hier der Code aus der Ableitung ausgeführt werden soll.
Delphi-Quellcode:
type
  TFoo = class
    public
      InFooObject : TObject;
      constructor Create;
      destructor Destroy; override; // ist in TObject als virtual deklariert, darum override
  end;

...

constructor TFoo.Create;
begin
  inherited; // den Code der Vorgänger-Klasse - hier TObject.Create - ausführen
 
  InFooObject := TObject.Create;
end;

destructor TFoo.Destroy;
begin
  InFooObject.Free;

  inherited; // den Code aus der Vorgänger-Klasse - hier TObject.Destroy - ausführen
end;
Hier mal deine Unit2 korrekt formuliert:
Delphi-Quellcode:
unit Unit2;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type
  TRechnen = class( TObject )
    public
      // virtual - weil diese Methode in der Regel überschrieben werden soll
      // abstract - weil es keine Basis-Implementierung gibt, eben halt abstrakt :o)
      function CalcIt( a, b : real ) : real; virtual; abstract;
  end;

  TAddition = class( TRechnen )
    public
      function CalcIt( a, b : real ) : real; override;
  end;

  TSubtraktion = class( TRechnen )
    public
      function CalcIt( a, b : real ) : real; override;
  end;

implementation

function TAddition.CalcIt( a, b : real ) : real;
  begin
    result := a + b;
  end;

function TSubtraktion.CalcIt( a, b : real ) : real;
  begin
    result := a - b;
  end;

end.

foerster7892 18. Feb 2012 21:41

AW: Versuche Objektorientierung zu lernen
 
Wenn du keine weiteren Anforderungen an dein Objekt hast, dann brauchst du auch keinen speziellen constructor . // bedeutet? was sind "weitere Anforderungen?"

Ich zitier mich kurz mal selber, dass hatte ich vorhin noch hinzu editiert weil ich mir mit meinem Verständnis nicht sicher bin!

Zitat:

Nur nochmal zum Verständnis:
Wenn ich inherited benutze dann greife ich auf die Funktion der Mutterklasse zu also:

constructor TAddtion.create;
begin
inherited;
end;

jetzt würde ich also wenn ich:

Rechnen:=TAddition.create;
Rechnen.calcit(a,b);

und dies würde bei mir dann in der Mutterklasse landen und somit würde nichts passieren da diese ja in meinem Bsp. leer ist.

Achso und danke jetzt funzts. Aber warum trat bei constructor create Eintrag nen Fehler auf?

(sry dass ich euch gerade mit Fragen über Fragen bombardiere aber ich will dass bis Mitternacht durch haben soweit^^)

Sir Rufo 18. Feb 2012 21:57

AW: Versuche Objektorientierung zu lernen
 
Zitat:

Zitat von foerster7892 (Beitrag 1151785)
Wenn du keine weiteren Anforderungen an dein Objekt hast, dann brauchst du auch keinen speziellen constructor . // bedeutet? was sind "weitere Anforderungen?"

Wenn du in der Klasse noch einige Voreinstellungen vornehmen möchtest.
Delphi-Quellcode:
type
  TFoo = class
  private
    FData : integer;
  public
    constructor Create;
    property Data : integer read FData write FData;
  end;

...

constructor TFoo.Create;
begin
  inherited;

  // wir benötigen diesen constructor nur, weil wir FData mit dem Wert 10 initialisieren wollen
  FData := 10;
end;
Zitat:

Zitat von foerster7892 (Beitrag 1151785)
Ich zitier mich kurz mal selber, dass hatte ich vorhin noch hinzu editiert weil ich mir mit meinem Verständnis nicht sicher bin!

Zitat:

Nur nochmal zum Verständnis:
Wenn ich inherited benutze dann greife ich auf die Funktion der Mutterklasse zu also:

constructor TAddtion.create;
begin
inherited;
end;

jetzt würde ich also wenn ich:

Rechnen:=TAddition.create;
Rechnen.calcit(a,b);

und dies würde bei mir dann in der Mutterklasse landen und somit würde nichts passieren da diese ja in meinem Bsp. leer ist.

Ja, und weil in dem constructor ja nichts passieren soll, dann kann man den auch gleich weglassen ;)
Zitat:

Zitat von foerster7892 (Beitrag 1151785)

Achso und danke jetzt funzts. Aber warum trat bei constructor create Eintrag nen Fehler auf?

Weil du in der Typ-Deklaration den constructor angegeben hattest, aber diesen nicht ausformuliert hast.
Delphi-Quellcode:
type
  TFoo = class
  public
    constructor Create;
    procedure DoSomething;
  end;

...

// Das hier fehlte bei dir !!!
constructor TFoo.Create;
begin
  inherited;

end;

procedure TFoo.DoSomething;
begin
  // some code
end;
Das meinte ich mit "Alles was du in der Typ-Deklaration angibst, musst du auch ausformulieren ...
Zitat:

Zitat von foerster7892 (Beitrag 1151785)

(sry dass ich euch gerade mit Fragen über Fragen bombardiere aber ich will dass bis Mitternacht durch haben soweit^^)

Hast ja noch eine gute Stunde ;)

Popov 18. Feb 2012 23:23

AW: Versuche Objektorientierung zu lernen
 
Noch was zu constructor und inherited usw. Wenn du zum constructor nichts beizutragen hast, dann laß ihn weg, denn jede Klasse leitet sich von der Basisklasse TObject und erbt schon mal den constructor. Den hast du also schon. Dein

Delphi-Quellcode:
constructor TFoo.Create;
begin
  inherited;
end;
schadet zwar nicht, bringt aber auch nichts. Nötig wird es erst wenn du etwas dazu schreibst.

Nun zum inherited. So manches Mal stellt man sich die Frage ob er nötig ist, denn es gibt oft keinen Unterschied wenn man den wegläßt. Jetzt nicht hauen wenn es nicht stimmt, ist schon lange her wo ich es nach geguckt habe, aber bei Klassen auf der untersten Ebene ist nichts da was inherited aufrufen könnte. Deshalb könnte man sich die Frage stellen wozu der nötig ist. Nötig ist es spätestens da wenn man seine Klasse von einer anderen ableitet und die schon etwas in Create stehen hat. Dann, ohne inherited, wird der Part übergangen und die Klasse funktioniert nicht. Also am besten immer nutzen, ob nötig oder nicht. Dann geht es einem ins Blut über und man vergisst es nicht.

himitsu 18. Feb 2012 23:30

AW: Versuche Objektorientierung zu lernen
 
Nicht Schaden?
Das
Delphi-Quellcode:
inherited
hat einen ganz bestimmten Grund, denn damit wird gesagt "führe die Methode des Vorfahren aus".

Wenn man etwas überschreibt, dann hat das meistens einen Grund.
Oftmals möchte man zusäztliche Dinge machen, wobei das "zusätzlich" bedeutet, daß man das Alte auch haben will.
Im Falle des Constructors, möchte man natürlich, daß die Teile der Vorfahren ebenfalls ordentlich initialisiert werden. :zwinker:

PS: Es kann nicht schaden, wenn man das Inherited schreibt, auch wenn es keinen Vorfahren gibt ... dann läßt es der Compiler einfach weg.
Es schadet aber oftmals, wenn man es vergißt, wenn es nötig wäre.

Tipp: leite dir mal ein TMemo ab, überschreib den Constructor und vergiß das Inherited.
Jetzt will ich mal sehn, wie du dich fragst "Wo ist mein Memo, ich seh ja garnichts?" und beim ersten Zugriff auf .Lines hoff' ich, du freust dich über die Exception. :roll:

Ja, bei TObject fällt es nicht auf, da dort aktuell nur ein leerer Constructor vorhanden ist, aber wer weiß, ob da in Zukunft nicht doch mal irgendwas darin ist. :stupid:

Popov 19. Feb 2012 01:25

AW: Versuche Objektorientierung zu lernen
 
Mir ist gerade ein nettes Beispiel eingefallen, ich hoffe es ist gut.

Es zeigt, wie ich hoffe, gut wozu der constructor, aber vor allem inherited gut ist. Ich habe eine Klasse von TStringList abgeleitet und im constructor Create mit Wochentagen gefüllt. Wenn ich nun in der Prozedur Button1Click das Objekt erstelle und gleich mit ShowMessage anzeigen lasse, ist die Liste bereits mit Daten gefüllt.

Ansonsten ist das eine normale StringList, ich kann also den Inhalt löschen oder bearbeiten. Aber als Unterschied zu StringList hatte sie am Anfang Daten drin.

Nun mal ein kleines Experiment: mal in
Delphi-Quellcode:
TWochenTageListe.Create
inherited auskommentieren.

Was sehen wir? Eigentlich keinen Unterschied(²). In beiden Fällen wird beim Klick auf Button1 eine Liste ausgegeben.

Ok, inherited wieder einsetzten und zum zweiten Beispiel unten gehen.

Delphi-Quellcode:
// --------- Eine Liste mit Wochentagen für Deutschland ----------------
// ----------------- Abgeleitet von TStringList ------------------------
type
  TWochenTageListe = class(TStringList)
    constructor Create;
  end;

constructor TWochenTageListe.Create;
begin
  inherited; // teste die Klasse mit inherited und ohne
  Add('Montag');
  Add('Dienstag');
  Add('Mittwoch');
  Add('Donnerstag');
  Add('Freitag');
  Add('Samstag');
  Add('Sonntag');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  slWochenTage: TWochenTageListe;
begin
  slWochenTage := TWochenTageListe.Create;
  try
    ShowMessage(slWochenTage.Text);
  finally
    slWochenTage.Free;
  end;
end;
Das oben war eine Liste für Deutschland. In Bayern sagt man aber nicht Samstag, sondern Sonnabend. Wir erstellen nun eine extra Klasse für die Bayern, aber keine neue Liste, sondern leiten die WochenTageListe für Bayern aus der WochenTageListe für Deutschland ab und ändern lediglich den Samstag in Sonnabend. Da wir die Klasse ableiten, erben wir die Liste, allerdings nur wenn wir inherited aufrufen.

Wieder ein kleines Experiment: mal in
Delphi-Quellcode:
TBayernWochenTageListe.Create
inherited auskommentieren.

Was sehen wir? Nichts! Wenn wir auf Button2 klicken, ist die Liste leer. Nicht mal Sonnabend steht drin. Mit inherited wird die Wochentage Liste geerbt, ohne nicht.

Delphi-Quellcode:
// ----------- Eine Liste mit Wochentagen für Bayern -------------------
// --------------- Abgeleitet von TWochenTageListe----------------------
type
  TBayernWochenTageListe = class(TWochenTageListe)
    constructor Create;
  end;

constructor TBayernWochenTageListe.Create;
var
  i: Integer;
begin
  inherited; // teste die Klasse mit inherited und ohne
  for i := 0 to Count - 1 do
    if Self[i] = 'Samstag' then Self[i] := 'Sonnabend';
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  slWochenTage: TBayernWochenTageListe;
begin
  slWochenTage := TBayernWochenTageListe.Create;
  try
    ShowMessage(slWochenTage.Text);
  finally
    slWochenTage.Free;
  end;
end;
Und noch ein letztes Experiment: wir setzen inherited nicht wie es soll am Anfang des constructors, sondern am Ende der Prozedur.

Was sehen wir? Eine Liste, aber kein Sonnabend, sondern Samstag. Als in der Schleife nach Samstag gesucht wurde, war die Liste noch nicht da.

Delphi-Quellcode:
constructor TBayernWochenTageListe.Create;
var
  i: Integer;
begin
  //inherited; //Auskommentiert
  for i := 0 to Count - 1 do
    if Self[i] = 'Samstag' then Self[i] := 'Sonnabend';

  inherited; // inherited am Ende
end;

² - Damit meine ich keinen sichtbaren Unterschied in Bezug auf das Experiment.

foerster7892 19. Feb 2012 13:51

AW: Versuche Objektorientierung zu lernen
 
Vielen Dank an alle hat mir unglaublich geholfen.

:dp::dp::dp::dp::dp:

PS.: Das Beispiel war super!

:dp::dp::dp::dp::dp:

himitsu 19. Feb 2012 15:17

AW: Versuche Objektorientierung zu lernen
 
Wobei man noch froh sein kann, daß beim Zugriff auf "Count" keine Exception auftrat, denn schließlich war zu diesem Zeitpunkt die Stingliste noch nicht initialisiert.
Daß keine Exception auftrat, liegt am Inneren der Count-Funktion, wo glücklicher Weise auf nichts "Schlimmes"/Kompliziertes zugegriffen wird.

Popov 19. Feb 2012 17:42

AW: Versuche Objektorientierung zu lernen
 
Meinst du mein Beispiel oben? Ich habe es mir gerade angeguckt, zwischen der Create der oberen Klasse und TObject Create steht nichts. Alles Leere. Und da Count - 1 eben -1 ergibt, läuft die Schleife kein einziges mal durch. Ich wollte zuerst Self[5] := 'Sonnabend' schreiben, aber das wäre dann zu heftig gewesen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz