CLASS PROCEDURE innerhalb einer Klasse

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Lorca
Beiträge: 20
Registriert: Di 3. Nov 2020, 12:25

CLASS PROCEDURE innerhalb einer Klasse

Beitrag von Lorca »

Hallo zusammen,

könnte mich wohl jemand aufschlauen? :)

In der Unit DB gibt es u.a. die Klasse: TStringField.
Hier ist im protected Bereich folgender Eintrag
protected
class procedure CheckTypeSize(AValue: Longint); override;



Was beduetet das CLASS Procedure?
Eine lokale Klasse schliesse ich an dieser stelle aus.



Herzlichen Dank im Voraus

Lorca

Benutzeravatar
theo
Beiträge: 8643
Registriert: Mo 11. Sep 2006, 19:01

Re: CLASS PROCEDURE innerhalb einer Klasse

Beitrag von theo »

Klassenmethoden funktionieren ohne Instanz.
Einfach gesagt: Du brauchst die Klasse nicht createn um diese Methode aufzurufen.
Z.B. "Klasse, sag mir was du kannst, bevor ich dich benutze" :wink:

https://www.freepascal.org/docs-html/ref/refsu28.html

wp_xyz
Beiträge: 3686
Registriert: Fr 8. Apr 2011, 09:01

Re: CLASS PROCEDURE innerhalb einer Klasse

Beitrag von wp_xyz »

"class procedure" ist eine "Klassenprozedur", also eine Methode, die im Kontext einer Klasse aufgerufen wird. Du brauchst dafür keine erzeugte Instanz, sondern nur eine Klasse. Der Aufruf wäre in dem von dir genannten Fall:

Code: Alles auswählen

TStringField.CheckTypeSize(...);
Das ist im Unterschied zu "normalen" Methoden, die im Kontext einer Instanz aufgerufen werden. In dem Beispiel wäre eine Instanz ein konkret erzeugtes TStringField, und der Aufruf würde lauten:

Code: Alles auswählen

var f: TStringField;
  f := TStringField.Create;  // oder wie auch immer...
  f.CheckTypesize(...);
Das Prinzip habe ich erstmals im Zusammenhang mit den Graphik-Klassen verstanden. Die Basisklasse sei TGraphic und davon werden TBitmap, TPortableNetworkgraphic, TJpegImage usw. abgeleitet. Es soll vor dem Öffnen einer Graphik-Datei festgestellt werden, welche dieser Klassen dafür zuständig ist. Genau dafür gibt es die Klassen-Funktion IsStreamFormatSupported. Jede dieser Klassen implementiert seine eigene Version dafür. Sie liest die ersten Bytes einer Datei ein und prüft, ob diese der typischen Signatur der jeweiligen Klasse entsprechen. Dafür braucht man noch keine Instanz, sondern es reicht Code der Klasse. Also geht man alle registrierten Graphik-Klassen durch, und prüft durch Aufruf von IsStreamFormatSupported, ob die betreffede Klasse diese für diese Graphik-Datei zuständig ist. Damit kann man dann die richtige Instanz erzeugen und die Datei lesen. Gäbe es keine Klassenprozeduren müsste man probehalber eine Instanz von TBitmap usw. erzeugen und diese wieder verwerfen, wenn der Header nicht stimmt.

Warf
Beiträge: 1562
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: MacOS | Win 10 | Linux
CPU-Target: x86_64
Wohnort: Aachen

Re: CLASS PROCEDURE innerhalb einer Klasse

Beitrag von Warf »

class procedure/function und class var sind das was in anderen Sprachen oft als static member bezeichnet wird. Das sind globale variablen und funktionen die einer Klasse zugeordnet sind, ohne eine instanz dieser klasse zu benötigen.
Der Vorteil davon ist zum einen die logische Zuordnung von den membern zu der Klasse, sowie das berücksichtigen von Sichtbarkeitsmodifikatoren (private, protected, public, etc.)

Beispiel singleton pattern:

Code: Alles auswählen

type

  { TTestClass }

  TTestClass = class
  private
    class var _instance: TTestClass;
  public
    foo: integer;
    class function Instance: TTestClass;
    constructor Create;
  end;

{ TTestClass }

class function TTestClass.Instance: TTestClass;
begin
  if TTestClass._instance = nil then
    TTestClass._instance := TTestClass.Create;
  Result := TTestClass._instance;
end;

constructor TTestClass.Create;
begin
  foo := 0;
end;

begin
  TTestClass.Instance.foo := 42;
  WriteLn(TTestClass.Instance.foo);
end.
Die class variable _instance ist privat, sodass sie nur innerhalb der klasse (z.b. der class methode Instance) verwendet werden kann. Die Klassenmethode Instance greift dann auf diese variable zu, falls diese noch nicht exsistiert, wird sie erstellt und dann zurückgegeben.

Pascal unterstützt keine Privaten Konsturktoren, weshalb die nutzung des Singletons nicht auf compiler ebene enforced werden kann (im gegensatz zu z.B. Java), d.h. es braucht zwar immer noch den guten willen des programmierers, aber im allgemeinen kann man mit so einem singleton pattern garantieren das es nur eine einzige instanz einer klasse gibt die von allen verwendet wird (z.b. hilfreich für datenbank verbindungen die von mehreren Klassen benutzt werden)

Besonders interresant wird das ganze in kombination mit generischen Klassen, da dann jede variable/funktion pro generischer spezialisierung vorliegt, was z.b. zum implementieren von caches verwendet werden kann.

hubblec4
Beiträge: 261
Registriert: Sa 25. Jan 2014, 17:50

Re: CLASS PROCEDURE innerhalb einer Klasse

Beitrag von hubblec4 »

Und dann gibt es noch die Methode: class constructor.
Diese Methode kann genuzt werden um class var's zu initialisieren.
Die Methode wird beim Programm start automatisch ausgeführt, sogar vor allen Initialization Sektionen von units.

Code: Alles auswählen

type

  { TTestClass }

  TTestClass = class
  private
    class var i: Integer;
  public
    class constructor Init;
  end;
  
  
  class constructor TTestClass.Init;
  begin
    i:=99
  end;
  
  
Zuletzt geändert von hubblec4 am Do 11. Feb 2021, 14:27, insgesamt 1-mal geändert.

PascalDragon
Beiträge: 301
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: CLASS PROCEDURE innerhalb einer Klasse

Beitrag von PascalDragon »

Warf hat geschrieben:
Mi 10. Feb 2021, 17:09
class procedure/function und class var sind das was in anderen Sprachen oft als static member bezeichnet wird. Das sind globale variablen und funktionen die einer Klasse zugeordnet sind, ohne eine instanz dieser klasse zu benötigen.
Bitte bedenke, dass es in Object Pascal die Unterscheidung zwischen den folgenden gibt:

Code: Alles auswählen

type
  TMyClass = class
      class procedure Test1;
      class procedure Test2; static;
  end;
Im ersten Fall hat die Methode einen gültigen, versteckten Self Parameter, der auf den eigenen Klassentyp zeigt (oder den der abgeleiteten Klasse, falls darüber aufgerufen). Außerdem können diese virtuell sein und überschrieben werden. Das existiert so zum Beispiel nicht in Java oder C++.
Der zweite Fall hat keinen versteckten Self Parameter, ist zuweisungskompatibel zu normalen Funktionszeigern (im Gegensatz zu Methodenzeigern) und entspricht damit den static Methoden von C++ und Java.
FPC Compiler Entwickler

Lorca
Beiträge: 20
Registriert: Di 3. Nov 2020, 12:25

Re: CLASS PROCEDURE innerhalb einer Klasse

Beitrag von Lorca »

PascalDragon hat geschrieben:
Do 11. Feb 2021, 14:05
Warf hat geschrieben:
Mi 10. Feb 2021, 17:09
class procedure/function und class var sind das was in anderen Sprachen oft als static member bezeichnet wird. Das sind globale variablen und funktionen die einer Klasse zugeordnet sind, ohne eine instanz dieser klasse zu benötigen.
Bitte bedenke, dass es in Object Pascal die Unterscheidung zwischen den folgenden gibt:

Code: Alles auswählen

type
  TMyClass = class
      class procedure Test1;
      class procedure Test2; static;
  end;
Im ersten Fall hat die Methode einen gültigen, versteckten Self Parameter, der auf den eigenen Klassentyp zeigt (oder den der abgeleiteten Klasse, falls darüber aufgerufen). Außerdem können diese virtuell sein und überschrieben werden. Das existiert so zum Beispiel nicht in Java oder C++.
Der zweite Fall hat keinen versteckten Self Parameter, ist zuweisungskompatibel zu normalen Funktionszeigern (im Gegensatz zu Methodenzeigern) und entspricht damit den static Methoden von C++ und Java.


Hallo PascalDragon und auch ein freundliches Hallo an theo, wp_xyz, Warf, und hubblec4

Euch allen meinen herzlichen Dank. :) für reichhaltige Info.

Ich kenne so ein Vorgehen als statische Klasse. Konnte jedoch die diesbezügliche Pascal Lösung nicht interpretieren bzw. verstehen.
Daher nochmals meinen ganz herzlichen Dank an euch allen. :)


Liebe Grüße
Lorca

Antworten