Forum > General

Method of Field as getter/setter for property

(1/2) > >>

soerensen3:
I'm trying to simplify declaring properties with my smart pointer class and I remember there was some way you could access a method of a field and use it for a getter or setter of another class containing this field. It might become more clear if you look at this code.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program Project1; uses  Classes; type   generic ITestProp < T: TObject > = interface    ['{B0585610-BE1D-449E-A5D7-08E6DA9A3692}']    function GetTestProp: T;    procedure SetTestProp(AValue: T);  end;   { TTestProp }   generic TTestProp < T: TObject > = class ( TInterfacedPersistent, specialize ITestProp < T > )    published      function GetTestProp: T;      procedure SetTestProp(AValue: T);      property TestProp: T read GetTestProp write SetTestProp;  end;   TClass1 = class              end;   TClass2 = class    protected      FTestProp: specialize TTestProp < TClass1 >;       FITestProp: specialize ITestProp < TClass1 >;     public // Both of these property definitions do not work at the moment.      property Prop: TClass1 read FTestProp.GetTestProp write FTestProp.SetTestProp; // Declaring the property without an interface      property Prop2: TClass1 read FITestProp.GetTestProp write FITestProp.SetTestProp; // Declaring the property with an interface  end; { TTestProp } function TTestProp.GetTestProp: T;begin end; procedure TTestProp.SetTestProp(AValue: T);begin end; beginend. With both property declarations I get an error like this: "project1.lpr(59,45) Error: Unknown record field identifier "GetTestProp"" (For all getters and setters). It doesn't help using a record instead of a class for the field. Was this feature removed or do I do anything wrong? I couldn't find it in the docs either.

Martin_fr:
This only works, if the field (FTestProp) is of type record.

soerensen3:
Unfortunately not even then:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program Project1; {$modeswitch ADVANCEDRECORDS} uses  Classes; type  { TTestProp }   generic TTestProp < T: TObject > = record    function GetTestProp: T;    procedure SetTestProp(AValue: T);    property TestProp: T read GetTestProp write SetTestProp;  end;   TClass1 = class  end;   TClass2 = class    protected      FTestProp: specialize TTestProp < TClass1 >;     public      property Prop: TClass1 read FTestProp.GetTestProp write FTestProp.SetTestProp; // Declaring the property without an interface  end; { TTestProp } function TTestProp.GetTestProp: T;begin end; procedure TTestProp.SetTestProp(AValue: T);begin end; beginend. 

soerensen3:
What however works is:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program Project1; {$modeswitch ADVANCEDRECORDS} uses  Classes; type  { TTestProp }   generic TTestProp < T: TObject > = record    FTestProp: T;    property TestProp: T read FTestProp write FTestProp;  end;   TClass1 = class  end;   TClass2 = class    protected      FTestProp: specialize TTestProp < TClass1 >;     public      property Prop: TClass1 read FTestProp.FTestProp write FTestProp.FTestProp; // Declaring the property without an interface  end;  beginend. But not with methods. I thought I've seen it with methods before (Maybe in combination with interfaces? But I tried that as well, see the original example). I might be wrong though..

Thaddy:

--- Quote from: soerensen3 on July 23, 2018, 12:42:52 pm --- Was this feature removed or do I do anything wrong? I couldn't find it in the docs either.

--- End quote ---
It was never a feature in the first place, at least out of the box.
But there is something like the MakeMethod function from KOL - which I happened to co-write  :P :P 8-)  - that takes a normal procedure or function with a dummy parameter and makes it into a method.
I will add an example later. Works also for Lazarus. Works also on arm.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$ifdef fpc}{$mode delphi}{$H+}{$endif}uses classes;type  TNotifyFunc = function(sender:Tobject):integer of object;    function readVar(dummy:pointer;sender:Tobject):integer;forward;  function MakeMethod( Data, Code: Pointer ): TMethod;forward; type  TMyClass = class  private    FField:Integer;    FEvent:TNotifyFunc;  public    constructor create;    Property Someproperty:TNotifyFunc read Fevent;  end;   constructor TMyClass.Create;  begin    inherited create;    Fevent := TNotifyFunc(MakeMethod(@self,@Readvar));    FField := 100;  end;     {* Help function to construct TMethod record. Can be useful to      assign regular type procedure/function as event handler for      event, defined as object method (do not forget, that in that      case it must have first dummy parameter to replace @Self,      passed in EAX/RAX to methods of object). } function MakeMethod( Data, Code: Pointer ): TMethod;begin  Result.Data := Data;  Result.Code := Code;end; function readVar(dummy:pointer;sender:Tobject):integer;begin  Result := TMyClass(sender).FField;end; var  test:TMyClass;begin  test := TMyClass.Create;  writeln(Test.Someproperty(test));  test.free;end.
Quite a bit of hackery but possible.

Navigation

[0] Message Index

[#] Next page

Go to full version