Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Ist das schon Klasse? (https://www.delphipraxis.net/102771-ist-das-schon-klasse.html)

Gonzo2 4. Nov 2007 15:19


Ist das schon Klasse?
 
Ich fange mit Delphi und Klassen erst an und verstehe noch nicht alles. Ist das hier schon eine Klasse?

Delphi-Quellcode:
type
  TTestClass = class(TObject)
  public
    procedure Hallo(Sender: TObject);
  end;

var
  Test: TTestClass;

procedure TTestClass.Hallo(Sender: TObject);
begin
  ShowMessage('Hallo Welt');
end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Test.Hallo(Sender);
end;
Und was mich vor allem interessiert und ich mir nicht erklären kann, wenn das eine Klasse ist, wieso brauche ich kein Create? Das funktioniert zwar auch

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Test := TTestClass.Create;
  Test.Hallo(Sender);
  Test.Free;
end;
aber brauchen tue ich es anscheinend nicht. Wenn ich mit einer Bitmap arbeiten will und sie ohne Create nutzen will, dann gibt es eine Fehlermeldung. Wieso kann ich hier eine Klasse sofort nutzen? Wieso kann ich hier Create nutzen, kann es aber auch lassen?

Neutral General 4. Nov 2007 15:23

Re: Ist das schon Klasse?
 
Hi,

Also. Ja das ist schon eine Klasse. Jedoch ist der Parameter der procedure Hallo unnötig. Lass ihn einfach weg.
Du brauchst in diesem Fall kein Create weil du in TTestClass.Hallo auf keine Variablen/Properties von TTestClass zugreifst. Deswegen geht das ganze gut. Man sollte jedoch trotzdem immer eine Instanz seiner Klasse erstellen und freigeben.

Gruß
Neutral General

mkinzler 4. Nov 2007 15:25

Re: Ist das schon Klasse?
 
Ein(e) Klasse(ntyp) beschreibt nur die Eigenschaften, welche die Objekte (Instanzen der Klasse) später besitzen.
Du kannst dir das wie eine Form vorstellen, mit deren Hilfe später die Objekte erzeugt werden.
Der Construktor erzeugt dann eine Instanz.
Eine Klassenvariable ist nur eine Referenz (Zeiger) der anfänglich kein Objket referenziert.

Gonzo2 4. Nov 2007 16:47

Re: Ist das schon Klasse?
 
Die Antworten beantworten meine Frage nicht ganz. Wäre das der übliche Weg

Test.Create;

dann wäre meine Frage beantwortet. Müßte man Create aufrufen um paar Variablen zu vereinbaren, würde das da pben reichen und das wäre der übliche Weg. Aber man macht es so

Test := TTestClass.Create;

um Speicher für das Objekt zu resiervieren. So lernt man es zumindest. Bei dem zweiten Beispiel wird im Speicher Platz resierviert und Test bekommt die Adresse zugewiesen. Das verstehe ich. Wenn ich aber ohne Create sofort

Test.Hallo(Sender);

schreibe, dann hat Test noch keine Adresse. Es greift auf irgendwo zu. Es ist also nicht egal. Bei zweiten Beispiel wird Platz im Speicher zugewiesen und Test bekommt die Adresse. Beim ersten Beispiel wird irgendwas aufgerufen. Aber beides braucht man nicht um das dritte Beispiel fehlerfrei auszuführen.

Phoenix 4. Nov 2007 17:16

Re: Ist das schon Klasse?
 
Das ist relativ einfach erklärt:

Der Speicher für ein konkretes Objekt das aus einer Klasse mittels Create erstellt wird, beinhaltet 'nur' die Variablen dieses Objektes.

Der ausführbare Code einer Klasse wird ja nicht für jedes Objekt in den Speicher kopiert, sondern der ausführbare Code existiert nur ein einziges mal.

Sobald Du innerhalb des Codes einer Klasse auf Self, oder eine andere Variable zugreifst, erst dann greifst Du auf den Speicherbereich zu, der beim Create erzeugt wird. Greifst Du nicht auf Variablen der Klasse zu, und auch nicht auf 'Self', so benötigt der Code auch nicht den SPeicherbereich des Objektes und läuft fehlerfrei durch.

Das ganze nennt sich dann eigentlich Klassen- bzw. auch Statische Methode. Also eine Methode, die man direkt auf der Klasse aufrufen kann, und dazu kein Objekt benötigt. Der Konstruktor Create ist technisch gesehen auch nur so eine solche statische Methode.

sirius 4. Nov 2007 18:07

Re: Ist das schon Klasse?
 
Zitat:

Zitat von Gonzo2
Test.Create; //Nur Aufruf des constructors ohne Speicherreservierung.

...

Test := TTestClass.Create; //Aufruf des Constructors und Speicherreservierung

Link

Normalerweise stellt sich deine Frage nicht. eine Klasse hat immer Variablen, ansonsten bräuchte man keine Klasse. Daheraus ist ja erst das Prinzip der OOP entstanden.

dominikkv 4. Nov 2007 18:29

Re: Ist das schon Klasse?
 
Heißen die Variablen in Klassen nicht Felder?

mkinzler 4. Nov 2007 18:34

Re: Ist das schon Klasse?
 
Ruft man einen Konstruktor nicht als klassenmethode sondern direkt im Objekt auf, so ist eine normale Methode. Bei einer Variable, welche nicht auf eine gültiges Objekt zeigt, kann dass dann aber zu Zugriffverletzungen führen.

idontwantaname 4. Nov 2007 19:00

Re: Ist das schon Klasse?
 
Ich verweise hier mal auf:
http://www.dsdt.info/grundlagen/sprache/oo.php

Gonzo2 5. Nov 2007 16:37

Re: Ist das schon Klasse?
 
Ich glaube nur Phoenix hat so richtig verstanden um was es mir in der Frage ging. Die anderen Antworten gehen mehr in Richtung - was ist Create und was ist der Unterschied wenn ich es so mache oder so.

Mir geht es um die Frage wieso ich kein Create bei meiner Nutzung der Klasse brauche. Das ist das Wichtige an meiner Frage. Ich hab mir vorher schon einiges durchgelesen und weiß wie man es machen sollte. Was ich jetzt nur noch wissen will ist, wieso dies und das trotzdem funktioniert. Wieso funktionieren einige Außnahmen. Das ist mir für das Verständnis wichtig.

Sirius schrieb, daß sich die Frage eigentlich garnicht stellt, denn was kann man mit sowas schon anfangen? Also da gibt es genug Möglichkeiten, z.b. dann, wenn man keine Prozedur, sondern nur ein Objekt zuweisen kann, aber eine Prozedur aufrufen will.

So wie ich Phoenix verstanden habe wird die Klasse nur einmal mit dem Programm zusammen in den Speicher geladen und mit Create wird ein Speicherbreich reserviert in dem die Daten des Objekts der Klasse gespeichert werden. Und da ich in meinem Beispiel nur eine Prozedur aufrufe und keine Daten nutze, kann ich mit der Klasse direkt arbeiten ohne ein Objekt bzw. einen Speicherbreich anzulegen. Stimmt das soweit?

Natürlich gehe ich davon aus, daß mit Variablen nicht die lokalen Variablen der Prozedur gemeint sind, dann das funktioniert auch ohne Create fehlerfrei:

Delphi-Quellcode:
procedure TTestClass.Hallo(Sender: TObject);
var
  a, b: Integer;
  s: String;
begin
  a := Random(10);
  b := Random(10);
  s := IntToStr(a+b);
  ShowMessage('Hallo Welt '+s);
end;
Weitere Test haben gezeigt, daß erst das hier nicht funktioniert:

Delphi-Quellcode:
type
  TTestClass2 = class(TObject)
  public
    FString: String;
    procedure Hallo(Sender: TObject);
  end;

var
  Test2: TTestClass2;
Delphi-Quellcode:
procedure TTestClass2.Hallo(Sender: TObject);
begin
  FString := 'Hallo Welt';

  ShowMessage(FString);
end;
Das auch nicht

Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
begin
  Test2.FString := 'Hallo Welt';
  Test2.Hallo(Sender);
end;
Kann man also sagen, daß, der korrekte Weg mit Klassen zu arbeiten der ist ein Objekt über Create anzulegen, aber soweit es nur um die Nutzung eine Prozedur ist, das Ganze auch ohne Create und Free geht?

mkinzler 5. Nov 2007 16:42

Re: Ist das schon Klasse?
 
Du hast aber die anderen beiträge nicht gelesen, sonst wäre dir die Antwort klar. Ruft man Methoden auf die Klasse auf, werden diese als Klassenmethoden ausgeführt, das Funktioniert solange man nicht auf Member der Klasse zugreift. Existiert keine Instanz, existieren diese auch nicht.

Phoenix 5. Nov 2007 16:43

Re: Ist das schon Klasse?
 
Zitat:

Zitat von Gonzo2
So wie ich Phoenix verstanden habe wird die Klasse nur einmal mit dem Programm zusammen in den Speicher geladen und mit Create wird ein Speicherbreich reserviert in dem die Daten des Objekts der Klasse gespeichert werden. Und da ich in meinem Beispiel nur eine Prozedur aufrufe und keine Daten nutze, kann ich mit der Klasse direkt arbeiten ohne ein Objekt bzw. einen Speicherbreich anzulegen. Stimmt das soweit?

Ja. Das ist (technisch gesehen) durchaus möglich. Es ist aber eigentlich.. sagen wir mal nicht die richtige Art und Weise ;-)

Zitat:

Zitat von Gonzo2
Kann man also sagen, daß, der korrekte Weg mit Klassen zu arbeiten der ist ein Objekt über Create anzulegen

Genau.
Zitat:

Zitat von Gonzo2
..., aber soweit es nur um die Nutzung eine Prozedur ist, das Ganze auch ohne Create und Free geht?

Fast. :zwinker: Werf mal einen kleinen Blick hierauf - zum Stichwort Klassenmethoden: http://www.dsdt.info/grundlagen/sprache/methoden.php

Wenn Du eine solche Prozedur / Funktion so baust, dass sie ohne die Felder der Klasse auskommt - also den Speicherbereich für die Variablen nicht benötigt - dann solltest Du sie auch als eine Klassenmethode deklarieren.
Wenn Du bei Deinem funktionierenden Beispiel also noch das Schlüsselwort class vor die Methode schreibst, dann ist alles in Butter.

Gonzo2 6. Nov 2007 06:28

Re: Ist das schon Klasse?
 
Zitat:

Zitat von mkinzler
Du hast aber die anderen beiträge nicht gelesen, sonst wäre dir die Antwort klar. Ruft man Methoden auf die Klasse auf, werden diese als Klassenmethoden ausgeführt, das Funktioniert solange man nicht auf Member der Klasse zugreift. Existiert keine Instanz, existieren diese auch nicht.

Keine Respektlosigkeit, nur war deine kurze Antwort sehr allgemein und geschrieben aus der Sicht und mit der Kenntnis eines Wissenden, für den das bereits zum Allgemeinwissen gehört. Ich hab nur etwas von Konstruktoren, Klassenmehhoden und Bahnhöfen verstanden.

Zitat:

Zitat von Phoenix
Wenn Du eine solche Prozedur / Funktion so baust, dass sie ohne die Felder der Klasse auskommt - also den Speicherbereich für die Variablen nicht benötigt - dann solltest Du sie auch als eine Klassenmethode deklarieren.

Verstehe ich das richtig, daß mir eine Ausnahme bei den Klassen und arbeiten mit den Objekten aufgefallen ist, wo ich fast richtig annahm damit arbeiten zu können, aber damit alles korrekt ist, ich noch class vor die Prozedur schreiben muß? Dann ist es eine Klassenmethode und dann kann ich offiziel und ohne eine Fehler begangen zu haben damit arbeiten, ohne ein Objekt anlegen zu müssen?

Dann wäre also das hier der richtige Weg?

Delphi-Quellcode:
type
  TTestClass3 = class
  public
    class procedure Hallo;
  end;

class procedure TTestClass3.Hallo;
begin
  ShowMessage('Beispiel 3');
end;
Das Problem und vor allem der große Unterschied scheint mir zu sein, daß ich es dann nicht über eine Variable machen kann

Delphi-Quellcode:
var
  Test3: TTestClass3;
Funktioniert nicht

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Test3.Hallo;
end;
Funktioniert

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TTestClass3.Hallo;
end;
Funktioniert

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Test3 := TTestClass3.Create;
  Test3.Hallo;
  Test3.Free;
end;
Somit habe ich entweder das alte Problem oder nicht 100% das Gleiche, denn entweder nutze ich die Klassenmethode, dann gehe ich nicht über ein Objekt, sondern über die Klasse, so habe ich es zumindest aus den in den Links beschriebenen Kursen verstenden, muß aber die Klasse davorschreiben, oder ich nutze Create. Es ist dann doch ein kleiner Unterschied zu dem ersten Beispiel von mir in dem ich es weder als Klassenmethode deklariert habe, dafür abe ohne Create mit der Variable auf dei Prozedur zugegriffen habe.

Ich weiß, ich bin eine Klette am A., aber ich würde es gerne 100% und ohne einen Hauch Zweifel verstehen.

mkinzler 6. Nov 2007 06:39

Re: Ist das schon Klasse?
 
Ich hatte den Vergleich mit einer (Guss-)Form gewählt, um den Vorgang allgemein zu beschreiben. Leider kann man den genauen Unterschied deiner beiden Beispiel nur erklären, wenn man etwas ins Detail geht. Eine (Objekt-)Methode wird immer auf eine Instanz einer Klasse angewendet, eine Klassenmethode auf die Klasse. Ein Konstruktor ist eine Kllassenmethode, da er ja eine Instanz erstellt; dh.h vor dem Aufruf gibt es diese ja noch nicht. In Delphi kann man aber Konstruktoren auch auf Objekte anwende, dann erstellen sie keine Instanzen, sondern setzen nur Eigenschaften.

Phoenix 6. Nov 2007 07:42

Re: Ist das schon Klasse?
 
Zitat:

Zitat von Gonzo2
Somit habe ich entweder das alte Problem oder nicht 100% das Gleiche, denn entweder nutze ich die Klassenmethode, dann gehe ich nicht über ein Objekt, sondern über die Klasse, so habe ich es zumindest aus den in den Links beschriebenen Kursen verstenden, muß aber die Klasse davorschreiben, oder ich nutze Create. Es ist dann doch ein kleiner Unterschied zu dem ersten Beispiel von mir in dem ich es weder als Klassenmethode deklariert habe, dafür abe ohne Create mit der Variable auf dei Prozedur zugegriffen habe.

Ich weiß, ich bin eine Klette am A., aber ich würde es gerne 100% und ohne einen Hauch Zweifel verstehen.

Nix gegen Kletten. Mir ist jemand lieber der sich damit intensiv auseinandersetzt als jemand der meint, er hätte es kapiert und dann doch noch Fehler macht ;-)

Dir fehlt glaub ich noch ein klein wenig Hintergrundinfo.

Also ganz grob:
Delphi-Quellcode:
var
  objektvariable: TKlasse;
erstellt einen Bereich im Speicher, der einen Pointer aufnehmen kann. Das Ding hat aber erstmal einen ungültigen Wert.

Delphi-Quellcode:
objektvariable := TKlasse.Create();
erstellt zuallererstmal einen Bereich im Speicher für das neue Objekt dieser Klasse - und gibt einen Pointer auf dieses Objekt zurück. Der Code im Konstruktur wird dann ausgeführt, wobei 'Self' auch auf den Objektspeicher zeigt. In diesem Objektspeicher ist allerdings nicht nur ausschliesslich der Platz für die Variablen (Felder) des Objektes reserviert. In diesem Objektspeicher ist auch ein Pointer auf den Codebereich der Klasse hinterlegt. Erst jetzt zeigt die objektvariable auf ein vollständiges gültiges Objekt.

Das hat folgenden Hintergrund:
Delphi-Quellcode:
var
  control: TControl;
begin
  control := TLabel.Create(self); // Label erzeugt, aber auf Control zugewiesen
  control.Parent := self;

  if control is TLabel then
  begin
    TLabel(control).Caption := 'Wuppdi';
  end;
end;
Es wird auf eine Objektvariable ein Objekt erzeugt, das gar nicht dieses Objekt ist, sondern davon abgeleitet wurde. Das ganze nennt sich Kovarianz. Das funktioniert, weil TLabel ja alle Eigenschaften von TControl erbt.

Weil ja Om objektspeicher auch ein Verweis auf die eigentliche Klasse steckt, funktioniert die Abfrage ob das control ein Label ist und auch der Cast.

Aus genau dem Grund kann Dein Beispiel
Delphi-Quellcode:
var
  objektvariable: TKlasse;
begin
  objektvariable.Machwas();
end;
nicht funktionieren: objektvariable KÖNNTE ja auf eine TKlasse zeigen - oder aber auch auf ein TIrgendwasAbgeleitetVonTKlasse. Da das der computer ja nicht wissen kann müsste er auf jeden Fall erstmal in das Objekt reingucken was hier referenziert wird um dann die richtige Methode auszuführen. Machwas() könnte in einer Ableitung ja auch überschrieben worden sein.

Der Aufruf direkt auf der Klasse muss funktionieren, weil hier ja keine andere Klasse in Frage kommen kann.
Wenn Du wie in Deinem letzten Beispiel ein konkretes Objekt erzeugst ist damit auch die entsprechende Klasse festgelegt - und damit auch klar, welcher Code dahintersteckt.

sirius 6. Nov 2007 08:08

Re: Ist das schon Klasse?
 
Zitat:

Zitat von Gonzo2
Ich glaube nur Phoenix hat so richtig verstanden um was es mir in der Frage ging. Die anderen Antworten gehen mehr in Richtung - was ist Create und was ist der Unterschied wenn ich es so mache oder so.

Was wolltest du machen? Eine Ratestunde?

Sowas liegt immer an ungenauen / schlecht formulierten Fragen :zwinker:
Und jeder sieht ja, was die vorhergehenden geschrieben haben und wiederholen es natürlich nicht. Sondern sie versuchen noch in eine andere Richtung zu denken, frei nach: "Was könnte der User gemeint haben?"


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:41 Uhr.

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