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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,b88383a5d9c51aa0 X-Google-Attributes: gid103376,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!feeder.news-service.com!feeder.erje.net!newsfeed.velia.net!noris.net!newsfeed.arcor.de!newsspool4.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Ada-Singleton-Why does it work like this? Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <5a7a870c-40e2-4803-8753-0f9cfd2b800f@k2g2000yql.googlegroups.com> <6d2b2c67-22fb-4283-87ab-58357e47d5ca@v39g2000yqm.googlegroups.com> <18883tufqaunz.gf51zy6m6gna$.dlg@40tude.net> Date: Fri, 27 Mar 2009 11:02:13 +0100 Message-ID: <18mv53mf50kqw$.1k3zsftqjzwk2$.dlg@40tude.net> NNTP-Posting-Date: 27 Mar 2009 11:02:13 CET NNTP-Posting-Host: a34cb220.newsspool1.arcor-online.net X-Trace: DXC=D9aAC7K=heH78PK[oJ2ng@ic==]BZ:afN4Fo<]lROoRA^YC2XCjHcbIUD^3igdJkgBWMVmZB On Thu, 26 Mar 2009 15:00:52 -0700 (PDT), Maciej Sobczak wrote: > On 26 Mar, 15:28, "Dmitry A. Kazakov" > wrote: > >>> Can you defend the idea that creation does not belong to the type? >> >> I think I can. Creation cannot be expressed in terms of values of the type. > [...] > > Makes sense. > What about... constructors? I mean the real ones. The real ones are magical things. > In other mainstream languages (you know, those with curly braces ;-) ) > and let's say in Ada 2015 as well, constructors are defined > *syntactically* within the type. The "constructors" of C++ are not constructors, but user-defined procedures called from the real constructor at certain stages of object construction. It is similar to Ada.Finalization.Initialize, but far better designed. (Except than unavoidable in C++ nonsense of the object type mutating during construction.) > If we consider the object creation as > something that does not belong to the type, then can we say that > having constructors in a type definition is just a convenient > distortion and not a clear expression of the *semantic* reality, where > constructor should be defined as the entity that is external to the > type? > > Something like: > > class X > { > public: > void doThis(); > void doThat(); > private: > // ... > }; > > // imaginary constructor of type X > X() > { > // make up the state of new object > } > > What is "inside" or "outside" might have no sense in Ada, but in Ada > terms the problem can be expressed as whether constructors should be > primitive operations of the given type. In my view neither the constructor nor the user-defined construction hook are primitive operations in traditional sense. That is, a primitive operation is defined on a class of types and its implementation has a separate body for each type from the class. I.e. f acts on T'Class and for each type S from the class T, there is a body S.f. This body is either inherited and then composed with a type conversion (S.f = S_from_T o T.f o T_from_S) or else is overridden by the user. A user-defined construction hook of T is neither inherited by S, nor overridden by the user. The "real constructor" of S calls the hook of T upon construction of S before it does the hook of S. That is a different way of procedural composition. It is additive. (Of course, when constructing hook of T is called on S, S is first converted to T and then back to S. This is a mere view conversion for by-reference types.) We could imagine some generalized model of a primitive operation in which a body of f for the type T would consist of some prologue, overridable part and epilogue. A derived type S would be able to extend the prologue and/or epilogue and to replace the overridable part. (This could be useful if you wanted to do transaction or concurrent stuff transparently. For example, the prologue could grab a lock, the epilogue would release it. The overridable part would do things.) However, even in this generalized model I would keep constructing/destructing hooks separate from primitive operations in order to prevent them called elsewhere than from compiler-generated constructors and destructors. Just for safety reasons. C++ people did it right, when they forbade explicit calls to T::T() and T::~T(). -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de