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/
next prev 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