ada

How to set up and derive a type from an abstract tagged record?


I'm having some difficulties getting my head around inheritance in Ada, and with some syntax.

My goal is to derive from an abstract type with a record, and use a different data type in the record field. Here's what I've been able to compile:

type Base is abstract new Parent.ParentType with record
    X:Access_Type;
end record

type Child is new Base with record
    n:Integer;
end record;

But I don't want to have this additional n field, I'd like to have X be an integer in the child type. I can't get the compiler to be happy with it. Something like the following is what I want:

type Base is abstract new Parent.ParentType with tagged record
    X:Access_Type;
end record;

type Child is new Base with record
    X:Integer;
end record;

Unfortunately, I can't figure out how to tag the base type which I think would allow me to reassign the X field. (Without tagging, the compiler complains of conflicting declarations.)

Can someone shed some light on this? I'm quite new to OO programming in general and I'm finding Ada's type approach more confusing than the usual class approach.


Solution

  • Base has to be tagged, because you can't say is abstract new Parent.Parent_Type unless Parent.Parent_Type is tagged, and that means that any derived type such as Base must be too.

    The problem is that, as you have it, any code that can see Child could see two Xs; the one in Base and the one in Child. The compiler won't let you be ambiguous; when others read your code and see My_Child.X, how will they know which X you meant?

    One way round this would be to make the full declaration of Base private, so that there's only one visible possibility for My_Child.X:

    package Bases is
       type Base is abstract new Parent.Parent_Type with private;
    private
       type Base is abstract new Parent.Parent_Type with record
          X : Float;
       end record;
    end Bases;
    
    with Bases;
    package Children is
       type Child is new Bases.Base with record
          X : Integer;
       end record;
    end Children;