Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi OOP / Methodenbezeichner: Anfängerfrage (https://www.delphipraxis.net/45385-oop-methodenbezeichner-anfaengerfrage.html)

Tso 5. Mai 2005 08:23


OOP / Methodenbezeichner: Anfängerfrage
 
Hallo & pardon schon im voraus für diese Anfängerfrage,

ich habe ein Problem von dem ich ausgehe, dass es relativ einfach gelöst werden könnte. Meine Google/-Forensuchergebnisse führten leider zu keinem Ergebnis.

Also ...

Der Code hier soll nur dazu dienen meine Frage zu verdeutlichen, ist also nur ein Beispiel:

Delphi-Quellcode:
procedure LabelRefresh;

  begin

  Label1.Caption := IntToStr(wert);

  end;
Ich packe diese Prozedur nun also in den implementations-Teil und würde sie gern weiter verwenden, dies geht jedoch nicht, weil ich dann die Fehlermeldung erhalte, dass Label1 ein 'undefinierter Bezeichner' sei.

Gut, der Fehler muss also irgendwo darin legen, dass nicht angegeben ist, dass Label1 zu TForm1 gehört ... Was dazu führte, dass ich den Code folgendermaßen modifizierte:

Delphi-Quellcode:
procedure LabelRefresh;

  begin

  TForm1.Label1.Caption := IntToStr(wert);

  end;
Funktionierte leider nicht wie erhofft, denn nun kommt der Fehler: 'Methodenbezeichner erwartet' ... Hm, mal fix in der Hilfe nachgesehen und ermittelt, dass man dieses Problem mit dem Bezeichner 'Self' beheben kann, was jedoch leider auch nicht funktioniert, weil 'Self (also konkret TForm1(Self).Label1.Caption) ebenso als undefinierter Bezeichner gewertet wird (fehlt da vlt. ein Eintrag bei den 'uses'?).

Naja, ich denke mal, dass Problem lässt sich einfach beheben, ist wahrscheinlich nur ein kleiner Zusatz ... Aber ich komm einfach nicht drauf.

Danke bereits für's Lesen!

[edit=sakura] [Klammern ersetzen] Mfg, sakura[/edit]

Ultimator 5. Mai 2005 08:32

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Delphi-Quellcode:
procedure LabelRefresh;
begin
  Form1.Label1.Caption := IntToStr(wert);
end;
Das T vorm Form1.Label1.Caption muss weg ;)

Igotcha 5. Mai 2005 08:35

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Das Problem mit "Self" umgehst Du, in dem Du

Delphi-Quellcode:
Var
  Form1: TForm1;
löscht.

Das ist aber Geschmackssache.

Gruß Igotcha

Tso 5. Mai 2005 08:36

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Hui! Erstens vielen Dank für die schnellen Antworten und zweitens vielen Dank für die Lösungsansätze! Die Sache mit dem 'Self' ist etwas das ich auch für spätere Dinge im Hinterkopf behalten kann! :)

maximov 5. Mai 2005 09:24

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Das gesammte problem tritt eigentlich nur auf, weil du deine procedure als normale globale prozedur deklarierst und nicht als methode einer speziellen klasse. Generell handelt man sich nur ärger ein, wenn man von globalen punkten lokale aufgaben direkt ausführt. Ich würd das als methode von TForm1 deklarieren, womit dnn auch self wieder verfügbar ist.

alcaeus 5. Mai 2005 09:36

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Ich kann mich Maximov nur anschliessen. Die Verwendung der globalen Form1-Variable ist eh das schlimmste was man machen kann. Wenn du ploetzlich Form2 als MainForm deklarierst, und dir darin eine Neue Instanz von TForm1 deklarierst, dann wirds krachen weil Form1 nicht unbedingt verfuegbar ist. Tipp: keine globalen Prozeduren Verwenden, Forms nicht automatisch erstellen lassen (kann in den Projektoptionen eingestellt werden), und die unit-globalen Form-Variablen (Form1: TForm1;) loeschen.

Greetz
alcaeus

Sharky 5. Mai 2005 10:49

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Als Alternative kannst Du an deine Procedure auch einfach das TLabel übergeben um welches es geht.
Delphi-Quellcode:
procedure LabelRefresh (aLabel : TLabel; value : Integer);
begin
  aLabel.Caption := IntToStr (value);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  LabelRefresh(Label1,10);
end;

Robert_G 5. Mai 2005 14:19

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Zitat:

Zitat von maximov
Das gesammte problem tritt eigentlich nur auf, weil du deine procedure als normale globale prozedur deklarierst und nicht als methode einer speziellen klasse. Generell handelt man sich nur ärger ein, wenn man von globalen punkten lokale aufgaben direkt ausführt. Ich würd das als methode von TForm1 deklarieren, womit dnn auch self wieder verfügbar ist.

Ja und nein.
Spezielle Klasse? Klaro! :)
Methode vom Form? hmmm... Schlecht bis gar nicht wiederverwendbar. ;)

Im Vorfeld würde ich das empfehlen. Dadurch geschieht der Rest einfach transparenter. :)

OK...
Im Menu unter View findest du den Project Manager. Öffne ihn mal und füge deiner Projektgruppe ein neues Projekt hinzu.
Es sollte ein Package sein. ;) Speichere es am Besten gleich als "LabelMitWertDings.dpk" ab.
Dem Package verpasst du eine neue Unit und speicherst diese als "uLabelMitWertDings.pas".

Wie man vielleicht sehen kann, wird das ene Ableitung von TLabel. Wir wollen also die alte Eigenschaft Caption verstecken und eine neue Eigenschaft vom Typ Integer einführen. Diese sollte dann hinter den Kulissen die Umwandlung Integer -> String durchführen um die Caption des Labels zu besetzen.

Außerdem sollten wir die Caption direkt im Constructor mit einer Zahl besetzen (sonst knallt es ja gleich von Anfang an :zwinker: )

Noch ein Register, um das Control in die IDE zu kriegen und das war's dann auch schon. :)

Los Unitos:
Delphi-Quellcode:
unit uLabelMitWertDings;

interface
   uses
      Classes,
      StdCtrls;

   type
      TLabelMitWertDings = class(TLabel)
      private
         fWertDings :Integer;
      protected
         property Caption;

         procedure setWertDings(const aValue: Integer);virtual;
      published
         property WertDings :Integer read fWertDings write setWertDings;
      public
         constructor Create(aOwner: TComponent); override;
      end;

   procedure Register(); // zum Installieren in die IDE

implementation
   uses
      SysUtils;

procedure Register();
begin
   RegisterComponents('Samples', [TLabelMitWertDings]);
end;

{ TLabelMitWertDings }

constructor TLabelMitWertDings.Create(aOwner: TComponent);
begin
   inherited Create(aOwner);
   WertDings := 0;
end;

procedure TLabelMitWertDings.setWertDings(const aValue: Integer);
begin
   fWertDings := aValue;
   inherited Caption := IntToStr(fWertDings);
end;

end.
Jetzt einfach im Project Manager einen Rechtsklick auf das Package und Install anklicken ->und *fump* schon ist das Control in der Komponentenpalette. (Wie im Code ersichtlich unter Samples)

Alles witere dürfte klar sein:
Delphi-Quellcode:
LabelMitWertDings.WertDings := 1;
Und zu den Tips mit den globalen Variablen des Formdesigners: Das kann doch nicht wirklich euer ernst sein? :shock:
Ich habe keine Ahnung warum Borland diesen Mist gebaut hat. Aber wer diese DAU-Krücken benutzt hat soviel Sinn für OOP bzw. wartbaren, fehlerresistenten Code wie meine Großmutter. (Eher noch weniger :roll: )

maximov 5. Mai 2005 16:08

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
@Robert_G: Ja, das ist mal wieder ein schöner rundumschlag :mrgreen: Am besten Tso verwendet gleich Interfaces, um diese konkrete aufgabe zu generalisieren und von der implementierung zu entkoppeln :wink:

@Tso: Willkommen in der Praxis :dp: ...und lass dich von uns OOP-lobbyisten nicht ins boxhorn jagen :cyclops:

Jens Schumann 5. Mai 2005 18:06

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Hallo Robert_G
toller Beitrag. Nur leider völlig am Thema vorbei :cyclops: . Tso's Problem ist, dass sie/er eine Komponente die sie/er auf ein Form gesetzt hat innerhalb einer globalen procedure aufrufen möchte. Das Problem ist mit einem erweiterten TLabel Nachfahren auch nicht gelöst (Es sei denn, man bastelt sich ein globale Instanz und erzeugt das Object im initialization Abschnitt - aber das wollen ganz bestimmt nicht machen :stupid: ). Ich halte maximov's Vorschlag keine globalen Methoden zu verwenden für den Besten.

Hinwies:
Du versteckst die published Caption property im protected Abschnitt :shock: wie unsauber.
Außerdem funktioniert das gar nicht unter Delphi. Dort gilt: Einmal published immer published. Egal was der Nachfahre macht.

Robert_G 5. Mai 2005 18:20

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Zitat:

Zitat von Jens Schumann
Hallo Robert_G
toller Beitrag. Nur leider völlig am Thema vorbei :cyclops: . Tso's Problem ist, dass sie/er eine Komponente die sie/er auf ein Form gesetzt hat innerhalb einer globalen procedure aufrufen möchte. Das Problem ist mit einem erweiterten TLabel Nachfahren auch nicht gelöst.

Erwischt! :P
Ich sah bei ihm das hier:
Delphi-Quellcode:
procedure LabelRefresh;
begin
  Label1.Caption := IntToStr(wert);
end;
Das heißt, diese Prozedur hätte eine fixe globale Variable genommen um ein fixes Label zu besetzen.

Dort wo Wert beschrieben wird, könnte er gleich die typisierte Property des "neuen" Labels besetzen.
Insofern ich es richtig verstanden habe? :gruebel:

Zitat:

Zitat von Jens Schumann
Ich halte maximov's Vorschlag keine globalen Methoden zu verwenden für den Besten.

Der gilt immer und überall. ;)

Zitat:

Zitat von Jens Schumann
Du versteckst die published Caption property im protected Abschnitt :shock: wie unsauber.
Außerdem funktioniert das gar nicht unter Delphi. Dort gilt: Einmal published immer published. Egal was der Nachfahre macht.

Das ist einfach nicht wahr, Jens. Gehe die Schritte von oben durch und du hast es in unter einer Minute auf deinem Form.
Wenn du jetzt noch die Eigenschaft "Caption" im OI siehst bekommst du 'nen Kasten Bier. :mrgreen:
Wenn du ohne Typecast auf TLabel/TCustomLabel/[alle Vorgänger bis TControl] an die Caption per Code zugreifen kannst, gibt's den nächsten. ;)

SirThornberry 5. Mai 2005 18:46

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
es macht aber auch keinen sinn etwas das einmal published war in protected zu verschieben. Denn durch casten auf den Vorgängertyp kann man ohne ableitung oder andere schwierigkeiten dann doch auf den wert zugreifen.

Robert_G 5. Mai 2005 18:56

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Zitat:

Zitat von SirThornberry
es macht aber auch keinen sinn etwas das einmal published war in protected zu verschieben. Denn durch casten auf den Vorgängertyp kann man ohne ableitung oder andere schwierigkeiten dann doch auf den wert zugreifen.

Ist alles richtig!
Aaaabeer wenn du dann bitte die Freundlichkeit hättest um den Typen mit Anlauf in den Hintern zu treten, der diese Property in TControl eingebaut hat OHNE den Setter als virtual protected zu deklarieren? (Ist übrigens der gleiche Getter/Setter wie bei Text :wall: )
Da TLabel kein richtiges WindowsControl sondern nur ein selbst gezeichnetes ist, kann man nichtmal auf die scheußliche WM_XXX-Vorschlaghammer -Methode eine Änderung des Wertes abfangen.
Es gibt also nur zwei Lösungen:
  • Man versteckt die Caption um die Wahrscheinlichkeit zu verringern, dass jemand einen Wert direkt dort reinwirft.
  • Man castet sich überall einen Wolf, freut sich, dass man Caption sichtbar gelassen hat und springt 3-mal im Kreis
Welcher von den beiden Wegen wäre etwas ... nunja ... "umständlich"?

Hansa 5. Mai 2005 20:02

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Insbesondere Robert : nur nicht nervös werden. Vor allem nicht mit Sachen rumwerfen, die nur in seltenen Spezialfällen gebraucht werden. 8) Was soll überhaupt gemacht werden ? Ein Label erhält ein zusätzliches integer-Feld, welches im OI eingestellt werden kann, oder ? Dieser Wert soll dann später als Caption angezeigt werden. Warum deshalb die Caption verschwinden soll ist mir schleierhaft und wohl auch eher uninteressant.

Delphi-Quellcode:
unit Intlbl;

interface

uses
  Windows, Messages, SysUtils, Graphics, Classes, Controls, DBCtrls, StdCtrls;

procedure Register;

type

  TIntLabel = class(TCustomLabel)
    private
      FWert : integer;
      procedure SetWert(const Value: integer);
    public
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
    published
      property Wert: integer read FWert write SetWert;
  end;

implementation

constructor TIntLabel.Create(AOwner: TComponent);
begin
  inherited;
  Wert := 0;
  Caption := IntToStr (Wert);
end;

destructor TIntLabel.Destroy;
begin
  inherited;
end;

procedure TIntLabel.SetWert(const Value: integer);
begin
  FWert := Value;
  Caption := IntToStr (Value);
end;

procedure Register;
begin
  RegisterComponents('Eigene', [TIntLabel]);
end;

end.
Reicht das nicht aus ? Falls eine kleinere Änderung eines Labels nur mit "virtual strict protected overload abstract" und dem verstecken vorhandener Sachen gemacht werden soll, dann aber ohne mich. 8) Falls es den Fragesteller überhaupt noch interessiert : alles schließen -> Datei -> neu -> weitere -> Package -> da den Code hier einfügen als Unit (vorher in Unit abspeichern). Dann noch compilieren und installieren. Was im OI in das Feld Wert eingetragen wird, das steht dann in der Caption.

Robert_G 5. Mai 2005 20:14

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
@Hansa
Hast du auch nur einen Fetzen von dem kapiert, was ich oben geschrieben habe?
Auch nur einen einzigen, klitzekleinen Fetzen? :roll:

Hansa 5. Mai 2005 20:39

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
ne :mrgreen:

Edit : allerdings habe ich Dein WertDings gesehen. Wollte es allerdings so machen, daß es geht und deshalb lieber selber neu. Ist doch sowieso nur ein Quickie. :lol:

Jens Schumann 8. Mai 2005 16:55

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Robert_G
Das ist einfach nicht wahr, Jens. Gehe die Schritte von oben durch und du hast es in unter einer Minute auf deinem Form.
Wenn du jetzt noch die Eigenschaft "Caption" im OI siehst bekommst du 'nen Kasten Bier. :mrgreen:
Wenn du ohne Typecast auf TLabel/TCustomLabel/[alle Vorgänger bis TControl] an die Caption per Code zugreifen kannst, gibt's den nächsten. ;)

Hallo Robert,
her mit dem Bier!
Ich habe das Problem auf folgenden Code reduziert und kann im OI wie erwartet die property Caption
Delphi-Quellcode:
sehen.
unit TestLabel;

interface

uses
  SysUtils, Classes, Controls, StdCtrls;

type
  TTestLabel = class(TLabel)
  private
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
    property Caption;
  public
    { Public-Deklarationen }
  published
    { Published-Deklarationen }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Beispiele', [TTestLabel]);
end;

end.
Siehe auch das Bild in der Anlage

Robert_G 8. Mai 2005 17:12

Re: [OOP / Methodenbezeichner] Anfängerfrage
 
Zitat:

Zitat von Jens Schumann
Hallo Robert,
her mit dem Bier!
Ich habe das Problem auf folgenden Code reduziert und kann im OI wie erwartet die property Caption sehen.

Hätte ich mich selbst an meine eigene Anleitung gehalten und das Ergebnis im Form designer (nicht nur im Code Editor) angesehen...
Hätte ich den Käse auch bemerkt. Aber es gibt nur einen Kasten, da die Eigenschaft nicht im Code Editor auftaucht. :zwinker: (auch wenn es keinen Compilierfehler gibt wenn man sie benutzt :wall: )

Ich erwarte dann eine PN mit Anschrift und Biermarke... :roll:

Ich bin eindeutig zu selten im Form designer :lol:


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:11 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