[gelöst] eigene Komponente Warnung

Rund um die LCL und andere Komponenten
Antworten
Benutzeravatar
juelin
Beiträge: 237
Registriert: Sa 24. Jul 2021, 18:03
OS, Lazarus, FPC: Linux Ubuntu 22. Windows 10 Delphi 11.3 (L 0.9.xy FPC 2.2.z)
CPU-Target: 64Bit
Wohnort: Mannheim

[gelöst] eigene Komponente Warnung

Beitrag von juelin »

Hallo,
ihr habt mir ja sehr gut geholfen bei meine eigenen Komponente TScore.
Es läuft auch alles proma.

Code: Alles auswählen

unit Score;

{$mode ObjFPC}{$H+}

interface

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

type
  TScore = class (TLabel)
    private
      FOnChange: TNotifyEvent;
      Vname: string;
      Stand: integer;
      Standalt: integer;
      procedure SetOnChange(AValue: TNotifyEvent);
    public
[Zeile 20} constructor Create(AOwner: TComponent; Besitzer: TForm; Vorname: string);
      destructor Destroy; override;
      procedure erhoehen(Wert: integer);
      Property OnChange:TNotifyEvent read FOnChange write SetOnChange;
      function getName: string;
      function getStand: integer;
  end;

implementation

constructor TScore.Create(AOwner: TComponent; Besitzer: TForm; Vorname: string);
begin
  inherited Create(AOwner);
  Parent:=Besitzer;
  Alignment:=taCenter;
  Autosize:=False;
  Color:=clNavy;
  Font.Color:=clYellow;
  Font.Name:='Arial Black';
  Font.Size:=16;
  Font.Style:=[fsBold];
  Height:=32;
  Left:=10;
  Top:=100;
  Transparent:=False;
  Visible:=True;
  Width:=962;
  Vname:=Vorname;
  Stand:=0;
  Standalt:=0;
end;

destructor TScore.Destroy;
begin
  inherited Destroy;
end;

procedure TScore.SetOnChange(AValue: TNotifyEvent);
begin
  if FOnChange=AValue then Exit;
  FOnChange:=AValue;
end;

procedure TScore.erhoehen(Wert: integer);
begin
  Stand:=Stand+Wert;
  if Stand <> Standalt then
  begin
    If Assigned(FOnChange) Then FOnChange(Self);
    Standalt:=Stand;
  end;
end;

function TScore.getName: string;
begin
  Result:=Vname;
end;

function TScore.getStand: integer;
begin
  Result:=Stand;
end;

end.
Nur bekomme ich beim Compelieren eine Warnung die ich nicht verstehe.
Und ich habe ja gelernt Warnungen wie Fehler zu behandeln.

Projekt kompilieren, Ziel: E:\Lazarus\Komponente\MyComponent.exe: Erfolg, Warnungen: 1
score.pas(20,24) Warning: An inherited method is hidden by "constructor Create(TComponent;TForm;AnsiString);"

Nun meine Frage:
a) was bedeutet diese Warnung
b) Wie kann man diese Warnung beseitigen

Danke für die Hilfe und Gruß
Jürgen
Zuletzt geändert von juelin am Fr 21. Feb 2025, 11:43, insgesamt 1-mal geändert.

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

Re: eigene Komponente Warnung

Beitrag von theo »


Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: eigene Komponente Warnung

Beitrag von Zvoni »

theo hat geschrieben: Fr 21. Feb 2025, 10:35 Probier mal mit einem "override" bei der Deklaration von Create.
https://www.freepascal.org/docs-html/ref/refsu32.html
https://www.freepascal.org/docs-html/ref/refsu27.html
Und in dem Fall ist TSCore ein Abkömmling von TLabel, welches wiederum ein Abkömmling von TCustomLabel ist, welches wiederum ein Abkömmling von TComponent ist.

Der Constructor Create von TComponent ist virtual, der Constructor Create von TCustomLabel ist bereits ein Override, TLabel überspringen wir, da TLabel nur die Properties von TCustomLabel published.

aus https://www.freepascal.org/docs-html/ref/refsu27.html
To be able to do this, the compiler keeps – per class type – a table with virtual methods: the VMT (Virtual Method Table). This is simply a table with pointers to each of the virtual methods: each virtual method has its fixed location in this table (an index). The compiler uses this table to look up the actual method that must be used at runtime. When a descendent object overrides a method, the entry of the parent method is overwritten in the VMT. More information about the VMT can be found in Programmer’s Guide.
Auf Deutsch:
Wenn eine virtuelle Methode des Vaters in einem Kind per "override" deklariert wird, wird der Eintrag in der VMT des Kindes mit der Adresse dieser "neuen" Methode überschrieben.
Heisst: Wenn ein Enkel eine Methode desselben Namens verwendet, schaut der Compiler in der VMT dessen Vaters nach, und findet eben dort den Eintrag in der VMT.

Vater.Methode;virtual; --> Eintrag in VMT von Vater
------------------
Kind.Methode;override; --> Eintrag in der VMT von Kind mit "neuer/eigener" Adresse von "Methode" --> wird somit wieder zu einer "virtual"-Methode
------------------
Enkel.Methode; --> Warnung! Es wurde ein Eintrag in der VMT bei "Kind" gefunden
Zuletzt geändert von Zvoni am Fr 21. Feb 2025, 11:11, insgesamt 2-mal geändert.
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

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

Re: eigene Komponente Warnung

Beitrag von theo »


Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: eigene Komponente Warnung

Beitrag von Zvoni »

theo hat geschrieben: Fr 21. Feb 2025, 11:06 Dann reintroduce?
https://wiki.freepascal.org/Reintroduce
Womit dann aber kein Zugriff auf "inherited" möglich ist

EDIT: Schmarrn. Natürlich kann inherited benutzt werden.
*grml*
Zuletzt geändert von Zvoni am Fr 21. Feb 2025, 11:09, insgesamt 1-mal geändert.
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

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

Re: eigene Komponente Warnung

Beitrag von theo »

Zvoni hat geschrieben: Fr 21. Feb 2025, 11:06
theo hat geschrieben: Fr 21. Feb 2025, 11:06 Dann reintroduce?
https://wiki.freepascal.org/Reintroduce
Womit dann aber kein Zugriff auf "inherited" möglich ist
Hier geht das und gibt keine Warnung.

Code: Alles auswählen

    public
      constructor Create(AOwner: TComponent; Besitzer: TForm; Vorname: string); reintroduce;
      ...
  end;

implementation

constructor TScore.Create(AOwner: TComponent; Besitzer: TForm; Vorname: string);
begin
  inherited Create(AOwner);

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: eigene Komponente Warnung

Beitrag von Zvoni »

theo hat geschrieben: Fr 21. Feb 2025, 11:08
Zvoni hat geschrieben: Fr 21. Feb 2025, 11:06
theo hat geschrieben: Fr 21. Feb 2025, 11:06 Dann reintroduce?
https://wiki.freepascal.org/Reintroduce
Womit dann aber kein Zugriff auf "inherited" möglich ist
Hier geht das.

Code: Alles auswählen

    public
      constructor Create(AOwner: TComponent; Besitzer: TForm; Vorname: string); reintroduce;
      ...
  end;

implementation

constructor TScore.Create(AOwner: TComponent; Besitzer: TForm; Vorname: string);
begin
  inherited Create(AOwner);
Ich weiss. Habs mit was anderem verwechselt.
bei virtual/override gehts vor allem um die Signaturen der Methoden.
Reintroduce nur um den Namen der Methode
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
juelin
Beiträge: 237
Registriert: Sa 24. Jul 2021, 18:03
OS, Lazarus, FPC: Linux Ubuntu 22. Windows 10 Delphi 11.3 (L 0.9.xy FPC 2.2.z)
CPU-Target: 64Bit
Wohnort: Mannheim

Re: eigene Komponente Warnung

Beitrag von juelin »

ja danke für die Hilfe.
Mit reintroduce funktioniert es.
Hatte aber bis heute noch nie was von reintroduce gehöhrt.
Also nochmal Danke
und Gruß
Jürgen

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: eigene Komponente Warnung

Beitrag von Zvoni »

Wäre dennoch vorsichtig damit
Aus dem zitierten Wiki-Eintrag
The modifier reintroduce allows a method of the parent class to be concealed by a new method with the same name.
....................
The modifier reintroduce merely suppresses a warning that a similar method already exists and that the programmer is aware of that.
Deutsch: "reintroduce" unterdrückt nur die Warnung, dass es bereits eine "ähnliche" Methode gleichen Namens gibt, und dass der Programmierer sich dessen bewusst ist.
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

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

Re: eigene Komponente Warnung

Beitrag von theo »

juelin hat geschrieben: Fr 21. Feb 2025, 10:28 Und ich habe ja gelernt Warnungen wie Fehler zu behandeln.
Wer hat dir das beigebracht?
Eine Warnung ist eine Warnung.
Die kann man sich anschauen und dann getrost entscheiden, dass sie in der vorliegenden Situation unproblematisch ist.
Ein Fehler ist etwas anderes.

Mein Auto warnt mich auch, wenn die Aussentemperatur unter 4 Grad geht (Glatteisgefahr).
Deswegen habe ich noch nie angehalten.

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

Re: [gelöst] eigene Komponente Warnung

Beitrag von wp_xyz »

Ich würde bei einer visuellen Klasse keinen überladenen Constructor einführen, denn wenn du die Komponente einmal in die IDE installieren willst (d.h. eigenes Icon auf der Komponenten-Palette), dann wird eh nur der geerbte Constructor (mit den einzigen Argument AOwner) verwendet, oder du nimmst das Wagnis auf dich, und schreibst für TScore einen eigenen Komponenten-Editor.

Zur Vereinfachung der Erzeugung einer Instanz von TScore zur Laufzeit würde ich einfach eine ganz normale Funktion, z.B. CreateScore, schreiben, die die nötigen Parameter (Vorname, evtl. auch Parent) als Parameter erhält.

Code: Alles auswählen

type
  TScore = class(TLabel)
    FVorname: String;
  ...
  public 
    constructor Create(AOwner: TComponent); override;
    property Vorname: String read FVorname write FVorname;  // oder nach published?
  published
    property Alignment default taCenter;
    property AutoSize default False;
    property Color default clNavy;
  end;
  
  constructor TScore.Create(AOwner: TComponent);
  begin
    inherited;
    Alignment:=taCenter;
    Autosize:=False; 
    Color:=clNavy;
    Font.Color:=clYellow;
    Font.Name:='Arial Black';
    Font.Size:=16;
    Font.Style:=[fsBold];
    Height:=32;
    Width:=962;
    Transparent:=False;
    Visible:=True;   // kann entfallen, ist schon als "true" geerbt
    Stand := 0;       // kann auch entfallen, wird automatisch auf 0 gesetzt
    Standalt := 0;   // dto.
  end;
        
function CreateScore(AOwner: TComponent; AParent: TWinControl; AVorName: String): TScore;
begin
  Result := TScore.Create(AOwner);
  Result.Parent := AParent;
  Result.Caption := AName;
  Result.Left:=10;
  Result.Top:=100;
end;
Ich habe oben auch noch ein paar Ergänzungen gemacht, damit Alignment etc. für das Komponenten-Streaming den richtigen Default-Wert haben (nur wichtig, wenn die Komponente zur Designzeit aufs Formular geklickt werden soll) (wahrscheinlich brauchst du auch andere Defaulteinstellungen für den Font, aber wie man das bei "Unter-Properties" macht, habe ich gerade nicht parat).

Was machst du übrigens mit der von TLabel geerbten Property Caption? Könnte da nicht dein "Vorname" hin? Den hättest du dann immer automatisch angezeigt. Falls du das nicht brauchst, bezweifle ich, dass TLabel der richtige Vorfahre für TScore ist.

Antworten