Properties in Interfaces

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Properties in Interfaces

Beitrag von braunbär »

Ich habe eine Weile herumprobiert, aber ich habe das Gefühl, die funktionieren überhaupt nicht (oder ich mach was falsch, bloss keine Ahnung was). Jeder Versuch, auf Interfacevariable.Property zuzugreifen, wird vom Compiler mit einer Fehlermeldung (cannot access... oder so ähnlich) quittiert.
Als workaround habe ich jetzt die Getter und Setter Methoden ins Interface genommen und in der Komponente public gemacht und die Property rausgeschmissen, das geht dann problemlos.
Hat jemand einen Link auf ein funktionierendes Beispiel für eine Property in einem Interface?

Mathias
Beiträge: 6167
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Properties in Interfaces

Beitrag von Mathias »

Kannst du mal ein Beispiel posten, welches nicht geht ?
Dann sieht man am ehesten, wo du einen Fehler machst.

Hier hast du was ähnliches gefragt. viewtopic.php?f=5&t=11824
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Properties in Interfaces

Beitrag von braunbär »

Oje, ich sehe gerade, ich habe das in einem ganz falschen Unterforum gepostet, sorry.

Mathias hat geschrieben:Hier hast du was ähnliches gefragt.

Eigentlich nicht. Das dort hat mit dieser Frage gar nichts zu tun. Dort ging es um automatische Quelltextvervollständigung.

Mathias hat geschrieben:Kannst du mal ein Beispiel posten, welches nicht geht ?

Hmm, ich habe fast gewusst, dass die Frage kommen wird. Ich habe blöderweise das ganze schon auf getter und setter im Interface geändert, da funktioniert es, und mir den Code von vorher nicht aufgehoben. Mit einem Link auf ein funktionierendes Beispiel würde ich wahrscheinlich sebst sehen, was ich falsch gemacht habe, deshalb erst einmal die Frage danach. Ich habe so ein Codebeispiel gesucht, aber nichts gefunden. In den Tutorials kommen keine Properties vor. Wenn niemand so was hat, spiele ich mich noch einmal damit, das Problem auf einen Minimalcode herunterzubrechen, der nicht funktioniert, und poste den dann hier.

Dass Properties nicht verwendet werden können, wenn das Interface mit externen nicht-Lazarus Programmen verwendet wird, steht in der Dokumentation. Aber bei mir handelt es sich um ein Interface, das nur programmintern verwendet wird. Das sollte ja funktionieren.

Mathias
Beiträge: 6167
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Properties in Interfaces

Beitrag von Mathias »

Hast du mal im wiki unter property geguckt ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Properties in Interfaces

Beitrag von braunbär »

Wenn da etwas zu properties in Interfaces steht, dann bin ich bei meiner Suche nicht darauf gestossen. Hast du einen Link?

Mathias
Beiträge: 6167
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Properties in Interfaces

Beitrag von Mathias »

Hast du einen Link?
http://wiki.freepascal.org/Property/de

Ich verstehe dich nicht ganz, was du mit interfaces meinst. Eine property wird immer in einer Class deklariert.
Die property befindet sich dabei im public-Teil.
Die Setter und Getter und auch die interne Variable befinden sich dann im private-Teil.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: Properties in Interfaces

Beitrag von wp_xyz »

braunbär hat geschrieben:Als workaround habe ich jetzt die Getter und Setter Methoden ins Interface genommen und in der Komponente public gemacht und die Property rausgeschmissen, das geht dann problemlos.
Hat jemand einen Link auf ein funktionierendes Beispiel für eine Property in einem Interface?

Im Interface IChartDrawer, das Alexander Kleinen für TAChart geschrieben hat, gibt es Properties (unit TADrawUtils):

Code: Alles auswählen

  IChartDrawer = interface
    ['{6D8E5591-6788-4D2D-9FE6-596D5157C3C3}']
    procedure AddToFontOrientation(ADelta: Integer);
    procedure ClippingStart(const AClipRect: TRect);
    procedure ClippingStart;
    procedure ClippingStop;
    procedure DrawingBegin(const ABoundingBox: TRect);
    procedure DrawingEnd;
    procedure DrawLineDepth(AX1, AY1, AX2, AY2, ADepth: Integer);
    procedure DrawLineDepth(const AP1, AP2: TPoint; ADepth: Integer);
    procedure Ellipse(AX1, AY1, AX2, AY2: Integer);
    procedure FillRect(AX1, AY1, AX2, AY2: Integer);
    function GetBrushColor: TChartColor;
    function GetFontAngle: Double;       // in radians
    function GetFontColor: TFPColor;
    function GetFontName: String;
    function GetFontSize: Integer;
    function GetFontStyle: TChartFontStyles;
    procedure SetDoChartColorToFPColorFunc(AValue: TChartColorToFPColorFunc);
    procedure Line(AX1, AY1, AX2, AY2: Integer);
    procedure Line(const AP1, AP2: TPoint);
    procedure LineTo(AX, AY: Integer);
    procedure LineTo(const AP: TPoint);
    procedure MoveTo(AX, AY: Integer);
    procedure MoveTo(const AP: TPoint);
    procedure Polygon(
      const APoints: array of TPoint; AStartIndex, ANumPts: Integer);
    procedure Polyline(
      const APoints: array of TPoint; AStartIndex, ANumPts: Integer);
    procedure PrepareSimplePen(AColor: TChartColor);
    procedure PutImage(AX, AY: Integer; AImage: TFPCustomImage);
    procedure PutPixel(AX, AY: Integer; AColor: TChartColor);
    procedure RadialPie(
      AX1, AY1, AX2, AY2: Integer;
      AStartAngle16Deg, AAngleLength16Deg: Integer);
    procedure Rectangle(const ARect: TRect);
    procedure Rectangle(AX1, AY1, AX2, AY2: Integer);
    procedure ResetFont;
    function Scale(ADistance: Integer): Integer;
    procedure SetAntialiasingMode(AValue: TChartAntialiasingMode);
    procedure SetBrushColor(AColor: TChartColor);
    procedure SetBrush(ABrush: TFPCustomBrush);
    procedure SetBrushParams(AStyle: TFPBrushStyle; AColor: TChartColor);
    procedure SetFont(AValue: TFPCustomFont);
    procedure SetGetFontOrientationFunc(AValue: TGetFontOrientationFunc);
    procedure SetMonochromeColor(AColor: TChartColor);
    procedure SetPen(APen: TFPCustomPen);
    procedure SetPenParams(AStyle: TFPPenStyle; AColor: TChartColor);
    function GetRightToLeft: Boolean;
    procedure SetRightToLeft(AValue: Boolean);
    procedure SetTransparency(ATransparency: TChartTransparency);
    procedure SetXor(AXor: Boolean);
    function TextExtent(const AText: String;
      ATextFormat: TChartTextFormat = tfNormal): TPoint;
    function TextExtent(AText: TStrings;
      ATextFormat: TChartTextFormat = tfNormal): TPoint;
    function TextOut: TChartTextOut;
 
    property Brush: TFPCustomBrush write SetBrush;
    property BrushColor: TChartColor read GetBrushColor write SetBrushColor;
    property Font: TFPCustomFont write SetFont;
    property Pen: TFPCustomPen write SetPen;
    property DoChartColorToFPColor: TChartColorToFPColorFunc
      write SetDoChartColorToFPColorFunc;
    property DoGetFontOrientation: TGetFontOrientationFunc
      write SetGetFontOrientationFunc;
  end;

Allerdings kann ich nicht sagen, warum er nur den Setter verwendet hat. Auf jeden Fall ist dieser öffentlicher Bestandteil des Interface, anders kann es ja auch nicht funktionieren, da ein Interface keine eigenen Daten hat.

Mathias
Beiträge: 6167
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Properties in Interfaces

Beitrag von Mathias »

Jetzt weis ich, was Braunbär mit interface meint. Ich dachte, er meinte das interface oben bei einer Unit.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Properties in Interfaces

Beitrag von Socke »

Properties aus Interfaces sind nicht automatisch in der implementierenden Klasse vorhanden. Sie sind mehr oder weniger nur Syntax-Kleber um nicht immer mit den Getter- und Setter-Methoden des Interfaces arbeiten zu müssen.

Code: Alles auswählen

program Project1;
{$Interfaces CORBA}
 
type
  IMyInterface = interface ['{7317CF7F-643D-43DD-B1AB-D1FF75C8859F}']
    function GetMyValue: Integer;
    procedure SetMyValue(AValue: Integer);
    property MyValue: Integer read GetMyValue write SetMyValue;
  end;
 
  TMyClass = class(TObject, IMyInterface)
  strict private
    fMyValue: Integer;
  public
    function GetMyValue: Integer;
    procedure SetMyValue(AValue: Integer);
  end;
 
function TMyClass.GetMyValue: Integer;
begin
  Result := fMyValue;
end;
 
procedure TMyClass.SetMyValue(AValue: Integer);
begin
  fMyValue := AValue;
end;
 
var
  o: TMyClass;
  i: IMyInterface;
begin
  o := TMyClass.Create;
  o.SetMyValue(5);
  i := o;
  WriteLn(i.MyValue);
  i.MyValue := 10;
  WriteLn(i.MyValue);
  // Error: identifier idents no member "MyValue"
  /// o.MyValue := 100;
  o.Destroy;
  ReadLn;
end.


Mathias hat geschrieben:Jetzt weis ich, was Braunbär mit interface meint. Ich dachte, er meinte das interface oben bei einer Unit.

Zur Vollständigkeit: Properties kann man auf überall verwenden, wo sie sinnvoll sind:
  • Klassen
  • Objekte
  • Interfaces
  • Records
  • Type/Class/etc. Helper
  • Units
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Properties in Interfaces

Beitrag von braunbär »

Socke hat geschrieben:Properties aus Interfaces sind nicht automatisch in der implementierenden Klasse vorhanden. Sie sind mehr oder weniger nur Syntax-Kleber um nicht immer mit den Getter- und Setter-Methoden des Interfaces arbeiten zu müssen.

Ok, dann (und mit dem beispiel von wp_xyz) ist mir klar, was bei mir falsch war. Das bedeutet aber auch, dass man bei einer Klasse, die eine Interface-Property implementiert, sowohl getter wie setter für die Property braucht, read Fxxxx und write Fxxxx geht dann nicht, weil die Variable Fxxxx kann im Interface natürlich nicht deklariert werden.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Properties in Interfaces

Beitrag von m.fuchs »

braunbär hat geschrieben:Das bedeutet aber auch, dass man bei einer Klasse, die eine Interface-Property implementiert, sowohl getter wie setter für die Property braucht, read Fxxxx und write Fxxxx geht dann nicht, weil die Variable Fxxxx kann im Interface natürlich nicht deklariert werden.

Ja, das ist leider eine Schwäche des Pascal-Interfacekonzeptes. Besser wäre es wenn ich im Interface nur eine Property fordere:

Code: Alles auswählen

type
  IMyInterface = interface
    property MyString: String;
  end;


Und dann kann jeder Entwickler selber entscheiden, wie er diese implementiert:

Code: Alles auswählen

type
  TMyClass = class(TObject, IMyInterface)
    private
      FMyString: String;
    public
      property MyString read FMyString write FMyString;
  end;


Man bräuchte dann noch einen Modifier für das Interface um auf Read- und WriteOnly-Properties hinzuweisen. Wäre so dann aus meiner Sicht flexibler.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Properties in Interfaces

Beitrag von Socke »

m.fuchs hat geschrieben:Ja, das ist leider eine Schwäche des Pascal-Interfacekonzeptes. Besser wäre es wenn ich im Interface nur eine Property fordere:

Du musst dann immer noch Methoden definieren, mit denen auf die Properties zugegriffen werden kann. Ansonsten hast du Properties, die du aussschließlich in der Klasse verwenden kannst, die das Interface implementiert, da anderswo gar nicht bekannt ist, wie das Property verarbeitet wird.
Hast du beispielsweise ein öffentliches Interface (Interface-Abschnitt der Unit), die implementierende Klasse ist aber nur im Implementation-Abschnitt definiert, hast du von anderen Units aus nicht einmal die Klassendefinition.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Properties in Interfaces

Beitrag von m.fuchs »

Socke hat geschrieben:Du musst dann immer noch Methoden definieren, mit denen auf die Properties zugegriffen werden kann. Ansonsten hast du Properties, die du aussschließlich in der Klasse verwenden kannst, die das Interface implementiert, da anderswo gar nicht bekannt ist, wie das Property verarbeitet wird.

Das ist ja grundsätzlich unwichtig, wie die Verarbeitung erfolgt. Also aus abstrakter Sicht. Das es in Pascal technisch nicht geht, weil Properties nur syntaktischer Zucker sind und den Zugriff auf Getter und Setter ein bisschen verstecken ist ja dann die Realität.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Properties in Interfaces

Beitrag von Socke »

m.fuchs hat geschrieben:
Socke hat geschrieben:Du musst dann immer noch Methoden definieren, mit denen auf die Properties zugegriffen werden kann. Ansonsten hast du Properties, die du aussschließlich in der Klasse verwenden kannst, die das Interface implementiert, da anderswo gar nicht bekannt ist, wie das Property verarbeitet wird.

Das ist ja grundsätzlich unwichtig, wie die Verarbeitung erfolgt. Also aus abstrakter Sicht. Das es in Pascal technisch nicht geht, weil Properties nur syntaktischer Zucker sind und den Zugriff auf Getter und Setter ein bisschen verstecken ist ja dann die Realität.

Man könnte diese Compiler-Magie durchaus implementieren, dann hat man aber plötzlich Properties, auf die man in Fremdbibliotheken gar nicht - nicht einmal über die Getter- und Setter-Methoden zugreifen kann. Damit ist die Interoperabilität, die man durch Interfaces gewonnen hat, nicht mehr gegeben.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Properties in Interfaces

Beitrag von af0815 »

BTW: Properties und Lazarus

Aktuell mit Problemen rechnen, wenn man Properties auf published setzt und das ganze in einer visuellen Komponente hat. Da hat es mit Lazarus Probleme gegeben. Dazu gabs hier im Forum und im englischen Forum Diskussionen, Bugfixes und 'Best practice'
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten