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,21960280f1d61e84 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!t-online.de!tiscali!newsfeed1.ip.tiscali.net!proxad.net!proxad.net!newsfeed.arcor.de!newsspool2.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: How come Ada isn't more popular? 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: <1169636785.504223.139630@j27g2000cwj.googlegroups.com> <45b8361a_5@news.bluewin.ch> <3pejpgfbki.fsf@hod.lan.m-e-leypold.de> <1sh134r4r8piq$.wh1w0uitf99t$.dlg@40tude.net> <83ozh.25895$yC5.16628@newssvr27.news.prodigy.net> Date: Sat, 10 Feb 2007 21:29:14 +0100 Message-ID: <1jj753ks550y9.1h2mmpoqk4pbf.dlg@40tude.net> NNTP-Posting-Date: 10 Feb 2007 21:28:56 CET NNTP-Posting-Host: 602c62a3.newsspool1.arcor-online.net X-Trace: DXC=aEITQ8i]2^3U`5g[@c]@J1ic==]BZ:af>4Fo<]lROoR1^YC2XCjHcb9GYX3fBd>A40DNcfSJ;bb[5IRnRBaCd04kEgJC78G=;UEA8[0hCM= X-Complaints-To: usenet-abuse@arcor.de Xref: g2news2.google.com comp.lang.ada:9240 Date: 2007-02-10T21:28:56+01:00 List-Id: On Sat, 10 Feb 2007 18:21:56 GMT, adaworks@sbcglobal.net wrote: > "Dmitry A. Kazakov" wrote in message > news:1sh134r4r8piq$.wh1w0uitf99t$.dlg@40tude.net... >> On Fri, 09 Feb 2007 07:50:43 -0500, Robert A Duff wrote: >> >>> Maciej Sobczak writes: >>> >>> >>> Why is that superior to just using functions as constructors? >>> Ada has: >>> >>> type T(<>) is ... >>> >>> to indicate that clients MUST call some constructor function when >>> creating objects. And it now allows constructor functions (and >>> aggregates) for limited types. >> >> Because it does not compose upon inheritance and aggregation. >> >> When inherited the constructing function need to be overridden, even if >> null record was the only thing added. Further one can barely publicly >> derive anything from T, which breaks encapsulation. >> > I guess I don't see this as a serious problem. Perhaps this is because > I frequently take the Modula-2 approach and create opaque types. > These support extensible inheritance, enforce encapsulation, and > separate all the implementation details within the package body. > > Granted, the use of opaque types requires the supporting capability > of access types. But the use of access types in the pursuit of good > programming is no vice. Rather, it is consistent with the counsel given > us over two score years ago by Maurice Wilkes. > > From my perspective, opaque types solve a lot of problems that are > inherent in C++ and Java and support an increased level of separation > of concerns in my application architecture. That being said, one can, > with a little effort, create C++ opaque types. I have not thought about > how this would be done in Java. Pehaps through the interface mechanism. Opaque types are nice, but I don't think that they solve the problem. Everything is OK as long as the types are independent. But when they are not, one would like to have operations defined on access T be ones of access S, (type S is new T with ...). The problem just reappears as composition of constructing functions for access T and access S. For example, GtkAda represents a practical example of this problem. It goes as follows: type Gtk_T_Record is ...; type Gtk_T is access Gtk_T_Record'Class; -- The opaque type procedure Gtk_New (X : out Gtk_T); -- Constructing "function" procedure Initialize (X : access Gtk_T_Record'Class); -- Constructor ... -- All operations are defined in terms of access Gtk_T_Record. -- The implementation of "constructors" goes as follows procedure Gtk_New (X : out Gtk_T) is begin X := new Gtk_T_Record; Initialize (X); exception when others => -- We don't want it leaking Free (X); raise; end Gtk_New; procedure Initialize (X : access Gtk_T_Record'Class) is begin ... -- Initialization end Initialize; Now with a derived type S: type Gtk_S_Record is new Gtk_T_Record with ...; type Gtk_S is access Gtk_s_Record'Class; -- The opaque type procedure Gtk_New (X : out Gtk_S); procedure Initialize (X : access Gtk_S_Record'Class); procedure Gtk_New (X : out Gtk_S) is begin X := new Gtk_S_Record; Initialize (X); exception when others => Free (X); raise; end Gtk_New; procedure Initialize (X : access Gtk_S_Record'Class) is begin Parent_Package.Initialize (X); ... -- Custom initialization end Initialize; This all is quite boring, at least. Neither Gtk_New nor Initialize are composable. Further, specifically to opaque types, it is impossible to hide Gtk_T implementation as an access type, which breaks encapsulation by exposing Gtk_T_Record to everybody. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de