Generics object and assignment overloading

Generics object and assignment overloading

type

  TMyObject = class

    property Value: T;

  end;

  TIntObject = TMyObject;

var

  obj: TIntObject;

  int: integer;

begin

  obj := TIntObject.Create;

  obj := 4;  // assigns 4 to obj.value

  int := obj; // resulting in Int being 4

end;

Is it possible to do operator overloads which allows the assignments as outlined above? I know this is not housebroken code – but it would help immensely for code simplicity in the specific context that I want to use it in. If possible, what are the pitfalls? (instances will not be persistent or streamed).

16 thoughts on “Generics object and assignment overloading


  1. You cannot overload assignment.  The closest you can get is to overload the implicit cast operator with operator overloading. Which leads you to this:


    {$APPTYPE CONSOLE}


    type


      TMyRec = record


        FValue: T;


        class operator Implicit(const Value: T): TMyRec;


        class operator Implicit(const Value: TMyRec): T;


      end;


    class operator TMyRec.Implicit(const Value: T): TMyRec;


    begin


      Result.FValue := Value;


    end;


    class operator TMyRec.Implicit(const Value: TMyRec): T;


    begin


      Result := Value.FValue;


    end;


    var


      value: TMyRec;


      int: integer;


    begin


      value := 666;


      int := value;


      Writeln(int);


    end.


    If only you’d asked this on Stack Overflow, others could have benefited in the future, rather than this being lost.


  2. David Heffernan It would be a nicety, not a necessicty. It wouldn’t hurt to get rid of the numerous .Value assignment references.


    MyClass.ThisField.Value := ref.ThisField; //int


    MyClass.ThatField.Value := ref.ThatField; //string


    contra


    MyClass.ThisField := ref.ThisField; //int


    MyClass.ThatField := ref.ThatField; // string


    There can be a lot of them.


  3. Lars Fosdal Wait, if you want this to be able to copy field values like that, why not just descend from TPersistent and use Assign?


    edit: sorry, silly friday suggestion. Brain is totally in weekend mode.


  4. These are editor wrappers that I am tinkering with – i.e. lots of once-off declarations.  No point in creating assigns for the umpteen variations of classes and editor combos. All I want to do is to minimize the code – and implicit would have done the job – had it been allowed for classes.


    Code extract


    TSupplierEdit = class(TEditorGrid)


      type


        TRepStatusEdit = TEditorGrid.TEnumComboListEditor;


        TBool = TEditorGrid.TEnumComboListEditor;


      private


    procedure SetSupplier(const Value: TPSDSupplier);


      protected


        SupplierId: TIntegerEdit;


        SupplierNo: TStringEdit;


        SupplierName: TStringEdit;


        SupplierGS1No: TStringEdit;


        SupplierGLN: TStringEdit;


        OtherList: TRepStatusEdit;


        Bool: TBool;


      public


        constructor Create(const aGrid: TAdvStringGrid); override;


        property Supplier: TPSDSupplier;


      end;


    constructor TSupplierEdit.Create;


    begin


      inherited;


      SupplierId := Add(‘Id’);


      SupplierId.ReadOnly := True;


      SupplierNo := Add(‘SupplierNo’);


      SupplierName := Add(‘Name’);


      SupplierGS1No := Add(‘GS1 No’);


      SupplierGLN := Add(‘GLN’);


      Status := AddComboList(‘Status’);


      Status.Value := ersNew; 


      Bool := AddComboList(‘Can do?’);


      Bool.OnElementToString :=


        function(value:Boolean):String


        begin


          case Value of


          False: Result := ‘Nope’;


          else Result := ‘Yup’;


          end;


        end;


    end;




    This is where I’d love to get rid of the .value ref.


    procedure TSupplierEdit.SetSupplier(const Value: TPSDSupplier);


    begin


      FSupplier := Value;


      SupplierEdit.SupplierId.Value := Supplier.Id;


      SupplierEdit.SupplierNo.Value := Supplier.SupplierNo;


      SupplierEdit.SupplierName.Value := Supplier.SupplierName;


      SupplierEdit.SupplierGS1No.Value := Supplier.SuppliersGS1No;


      SupplierEdit.SupplierGLN.Value := Supplier.SuppliersGLN;


      SupplierEdit.OtherList.Value := ersRetry;


      SupplierEdit.Bool.Value := True;


      SupplierEdit.PopulateGrid;


    end;


    No, I don’t want to use RTTI – as that only would work it for some of the use cases – unless I could somehow pass a class.property by reference and extract the property type from it as well as capturing getter and setter.


    I am full of wishful thinking, it seems.


  5. Any approach using a record will not work (or requires some nasty workarounds) or is just not worth it so save 6 characters of optimal code.


    What you are trying here is some kind of operator lifting for the assign operator depending on the right side of the assignment. Delphi does not support that – the closest approach I can think of is really what I did with the observable in knockoff (I also blogged about it) – but it will not be suitable for you because due to the nature of anonymous method types you cannot access any other members on such a type. But that type is not to save 6 characters anyway.


  6. it’d possible if property could be marked as “default” like we do with indexed [] properties, but then, how do you set the obj itself?


    Looking your code, I think Supplier needs some assign method to do SupplierEdit.Assign(Supplier). At least, all .Value:= get isolated, hidden out of view.

Leave a Reply