Search code examples
adaaccessor

Equivalent to accessors in Ada


Is there a way to create an equivalent to C# get/set in Ada ?

I have a type like this (in Ada) :

-- Ada :
type MyType is record 
    Value : Integer;
end record;

I want to split the value like this

-- Ada :
type MyType is record 
    ten  : Integer;
    unit : Integer;
end record;

But I want to keep MyType.Value (referenced in many readonly files). I want to create an accessor but I did not find how to do in Ada. I know how to do in C# :

// C# :
int Value
{
    get
    {
        return this.ten * 10 + this.unit;
    }
    set
    {
        this.unit = value % 10;
        this.ten = value / 10;
    }
}

What I want to do :

-- ada :
MyType var := MyType'(Value => 15); -- unmodified code
var.Value := 65; -- can be modified like before

Integer ten := var.ten; -- new getter

Solution

  • As I said in the comment of my answer to your previous question, There's no language construct that does it for you. Depending on your use-case, you could possibly employ controlled types:

    type MyTypeView (Data : not null access MyType) is limited
      new Ada.Finalization.Limited_Controlled with record
       Value: Integer;
    end record;
    
    overriding procedure Initialize (Object : in out MyTypeView) is
    begin
       Object.Value := Object.Data.ten * 10 + Object.Data.unit;
    end Initialize;
    
    overriding procedure Finalize (Object : in out MyTypeView) is
    begin
       Object.Data.ten := Object.Value / 10;
       Object.Data.unit := Object.Value mod 10;
    end Finalize;
    

    This would allow you to alter the Value in the way you want with the View:

    declare
       --  assuming MyObj is an object of type MyType
       View : MyTypeView (MyObj'Access);
       --  Initialize will be called, setting View.Value
    begin
       --  can access value as "property"
       Do_Something (View.Value);
       --  can assign value as "property"
       View.Value := 123;
       --  when View goes out of scope, Finalize will be called, updating MyObj
    end;
    

    Note however that as long as View lives, View.Value is detached from the original object, meaning that at the end;, other modifications of MyObj that happened after View has been created will be discarded. In a single-threaded program, this means that you may not call any subroutines that may instantiate a View of the same object while the current view lives (and may not directly instantiate a second View of this object inside the block).