From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!news.szaf.org!news.gnuher.de!rz.uni-karlsruhe.de!feed.news.schlund.de!schlund.de!news.online.de!not-for-mail From: Felix Krause Newsgroups: comp.lang.ada Subject: Re: orthogonal inheritance and extension aggregates Date: Tue, 23 Jul 2013 00:03:11 +0200 Organization: 1&1 Internet AG Message-ID: References: <6995bf02-6143-4d0f-aeb3-89a94bc1ac01@googlegroups.com> <79e0bc53-5431-493d-95d1-aac74c7d19c9@googlegroups.com> <947d8137-edc1-4abc-92b6-ace9dcec9bbb@googlegroups.com> NNTP-Posting-Host: pd9543795.dip0.t-ipconnect.de Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Trace: online.de 1374530591 14583 217.84.55.149 (22 Jul 2013 22:03:11 GMT) X-Complaints-To: abuse@einsundeins.com NNTP-Posting-Date: Mon, 22 Jul 2013 22:03:11 +0000 (UTC) User-Agent: Unison/2.1.10 Xref: news.eternal-september.org comp.lang.ada:16487 Date: 2013-07-23T00:03:11+02:00 List-Id: 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 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 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 > { my_class(size_type n) : extended(std::vector(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/