comp.lang.ada
 help / color / mirror / Atom feed
From: Felix Krause <flyx@isobeef.org>
Subject: Re: orthogonal inheritance and extension aggregates
Date: Tue, 23 Jul 2013 00:03:11 +0200
Date: 2013-07-23T00:03:11+02:00	[thread overview]
Message-ID: <kska6v$e7n$1@online.de> (raw)
In-Reply-To: 947d8137-edc1-4abc-92b6-ace9dcec9bbb@googlegroups.com

On 2013-07-22 18:59:29 +0000, Adam Beneschan said:

> OK, I've thought about this a little more.  First of all, I think the 
> problem might be unique to Ada.  Ada allows you to write a generic that 
> takes an arbitrary tagged type and defines a new extension of that 
> type.  The one other OOP language I'm most familiar with, Java, just 
> doesn't allow this:
> 
>    public class ExtensionOf<T> extends T is ...
> 
> is illegal.  (T is a "type variable" which is pretty much the 
> equivalent of a generic formal tagged type, and "extends" is how you 
> write derived types; but "extends" doesn't allow "type variables" in 
> its syntax.)

Just as an example, this would be how one could do it in C++:

    template<class T>
    class extended : public T {
       int i; // some meaningless extension to the base class
    public:
       extended(const T& other) : T(other), i(42) {}
    };

    class my_class : public extended<std::vector<int> > {
       my_class(size_type n) : extended(std::vector<int>(n)) {}
    };

I think there are some interesting things to note here:

 * C++ has no means of explicitly making the intermediate class 
abstract. However,
   if one would define at least one pure virtual (= abstract) method in 
there, it
   would be abstract, and the example would still work. The important 
thing here is
   that unlike Ada, C++ allows constructors for abstract types. In Ada, 
it is impossible
   to provide a generic Create_Extended function like you suggest if 
the type is abstract.
 * C++ makes heavy use of so-called copy constructors, ie. constructors 
that take another
   value of the same type as parameter and create a copy of that value. 
The compiler
   automatically generates a copy constructor if the class meets 
certain criterias.
   In this case, I use the copy constructor of std::vector to create a 
constructor
   of my_class that is similar to the corresponding constructor of std::vector.

So, Ada's primary problem seems to be that one cannot define a 
constructor-like method for
an abstract type. Now the Ada Style Guide at wikibooks tells us

    Consider splitting the initialization and construction of an object. [1]

Let's try to port the idea of an extended creation method to this pattern:

    procedure Init (Obj : in out Extended; From : Parent'Class);

It's important that Init is not a primitive operation of Extended, 
because child
initialization methods may need additional arguments. So it should be 
defined in a nested
package or something:

    package Initialization is
       procedure From_Parent (Obj : in out Extended; From : Parent'Class);
    end Initialization;

By the way, the Style Guide advices the same for constructors (putting 
them in a nested
or child package). While this seems to be a bit bloat, it does solve 
the inheritance problem.

An important issue with this solution is that one should somehow keep 
track of the
initialization status of the object (because if initialization does not 
happen at allocation
automatically, the object may be used uninitialized). The tagged type 
should have a function
"Initialized" that returns a Boolean. As soon as a tagged type does 
provide this mechanism,
all child types need to implement it too (provide an own initialization 
function that calls
one of its parent's initializers), so that this state is consistent 
throughout the type
hierarchy.

The problem is that the Ada language does not endorse this or any other 
pattern. In
C++, copy constructors are the way to go because the language supports 
them aggressively.
In Ada, it may be inconvenient to check Initialized every time before 
we use an object in
any way (well, Ada 2012 has the Pre aspect for such things). And now 
the most important thing:
For this to work in the case I described in my first post, the base 
type given as generic
parameter needs to implement this pattern! Because From_Parent is not 
implementable with
extension aggregates (one cannot assign a value to an abstract type), 
so we would need to
have an initialization method for the Vector type. This is why Ada 
should endorse some
pattern of object construction: If I define one myself, it may work 
with my own code,
but it's just not interoperable with the standard library types or 
potentially third-party
code.


 [1]: 
http://en.wikibooks.org/wiki/Ada_Style_Guide/Object-Oriented_Features#Constructors 


-- 
Felix Krause
http://flyx.org/

  parent reply	other threads:[~2013-07-22 22:03 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-19 17:46 orthogonal inheritance and extension aggregates Felix Krause
2013-07-19 18:00 ` Adam Beneschan
2013-07-22 16:02   ` Adam Beneschan
2013-07-22 18:44     ` Dmitry A. Kazakov
2013-07-22 18:59     ` Adam Beneschan
2013-07-22 19:19       ` Adam Beneschan
2013-07-22 22:03       ` Felix Krause [this message]
2013-07-19 19:05 ` Dmitry A. Kazakov
2013-07-20  5:49   ` Randy Brukardt
2013-07-20  6:36     ` Dmitry A. Kazakov
2013-07-20  7:54       ` Niklas Holsti
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox