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=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6b6619eb9cada212 X-Google-Attributes: gid103376,public From: Chris Powell Subject: Re: Help me to chose between ADA 95 and C++ Date: 1999/12/23 Message-ID: <3861F757.AE7776C7@rdel.co.uk> X-Deja-AN: 564383265 Content-Transfer-Encoding: 7bit References: <01bf37fb$a91afb60$0564a8c0@IS-D2D04C.test> <829rbv$a8m$1@nntp6.atl.mindspring.net> <01bf3e32$0b9dc880$022a6282@dieppe> <385112AE.7E2CFA9@rdel.co.uk> <3855e3cd_1@news1.prserv.net> <38561A6C.5DE3D901@rdel.co.uk> <38567806.FD1F4232@averstar.com> X-Accept-Language: en Content-Type: text/plain; charset=us-ascii X-Complaints-To: postmaster@rdel.co.uk X-Trace: rdel.co.uk 945944435 26926 172.16.10.14 (23 Dec 1999 10:20:35 GMT) Organization: Blackbox Software UK Ltd Mime-Version: 1.0 NNTP-Posting-Date: 23 Dec 1999 10:20:35 GMT Newsgroups: comp.lang.ada Date: 1999-12-23T10:20:35+00:00 List-Id: Sorry for the delay in my response... Tucker Taft wrote: > This choice of "static" over "dynamic" binding was very explicit > in the language design. By making static binding the default, > you minimize unexpected coupling between a parent type and a derived > type. I'll say more below... I have always viewed this coupling as part of the desired behaviour of OO. If the base class has defined a dispatching method it is explicitly declaring that the derived class may change the default behaviour (if any) of the base class. Why would the base class explicitly declare this intention, only to then deny the derived class its behaviour by default? It would be bad OO design if a base class was dependent on specific behaviour in a derived class rather than the logical semantics of the method, and I do not believe it is the language's job to 'tolerate' this. > I would have said that a common mistake in most OO languages > is to use dynamic binding between dispatching methods > when static binding would have been better. I find it confusing that a dispatching method isn't dispatching by default all the time. > I remember attending a panel session at OOPSLA several years ago where > essentially all of the panel members were griping about the difficulties > of doing maintenance and enhancement on class libraries when users are > taking advantage of this internal redispatching (also called "self > dependencies"). Users were overriding some but not all of the operations, > and then relying on this overriding to subtly affect the semantics of the > inherited operations. When the next version of the class library came out, > these users were very annoyed if the subtle effects were different. > This problem would not occur in a language like Ada 95 where the default > binding between dispatching operations is static. The developer of the class > library would only use redispatching if they felt it were part of the > *specification* of the operation, and hence would be intending to > document it. By contrast, in C++, Java, Eiffel, Smalltalk, etc., > redispatching is the default (and except for C++, static binding > is not even an option), so these kinds of self dependencies are produced > everywhere and anywhere there are calls between dispatching operations. > Quite often these were calls made out of convenience of implementation > of the operation, not out of an intent to create a subtle linkage > between the operations from an inheritance point of view. What if only those methods that are intended to be overriden are made dispatching operations? Both C++ and Ada 95 give the choice as to whether a method is overridable or not. It would be an error in the design of the class library's base class if it depended on specific behaviour in the derived class, or if it allowed essential base class behaviour to be overridden and thus lost. I can see there would be a problem if the language makes all operations dispatching, but this is not the case in C++. However, I have seen many examples of C++ class libraries defined with all methods virtual 'just in case' a derived class needs to do something unforseen. I do not agree with this approach. > It also means that binary operations are very > natural in Ada 95, whereas they are awkward and somewhat arbitrarily > asymmetric in languages like C++ and Java (e.g. the nasty need to > write "if S1.equal(S2) {" in Java, rather than "if S1 = S2 then" in > Ada 95, or the awkward connection between operator "friends" in C++ > and the "associated" class). Functions may be defined in C++ as binary operations by declaration outside a class, e.g. class Person { ... friend Marry( Person&, Person& ); // Only needed in Marry needs access to private data/methods }; void Marry( Person&, Person& ); > Personally the problem I have with the "state"-oriented model is > for various operations that have two or more objects involved, > and it is not at all obvious which one is the "primary" object. Here, neither person is the 'primary' object: probably both objects are updated with the details of their partner. > We certainly debated multiple inheritance. I think we were reluctant > to build in syntax for a feature that seemed in some cases a > solution looking for a problem. Also the fact that the designers of > C++ couldn't decide between "virtual" and "non-virtual" base classes, > and felt obliged to support both, and that many Eiffel uses of > multiple inheritance seemed to represent "uses" rather than "is-a" > relationships, made us feel that multiple inheritance was still in an awkward > stage of development. As a programmer looking for tools to support the abstraction of problems into code, I would sooner have both than neither. I would be happy with an implementation of MI that only allowed mix-in inheritance, where classes do not overlap and all methods must be unique. > The one thing I would add now to Ada 95 would probably > be something more akin to the Java multiple inheritance of interfaces. > Inheriting implementations from multiple parents seems quite error prone, > but inheriting interfaces is pretty clean. Yes, but I will then have to 'cut and paste' the common code behind multiple uses of an interface, and cut and paste leads to unmaintainable, error prone code. What are the chances of all the code behind an interface being different? On the one hand, I like Ada for its 'programmer protection' mechanisms; on the other I regret losing what I consider powerful or natural features and behaviour because of common programming mishaps. C++ seems to be geared to providing all the power with no regard for the abilities of an average programmer. Scary. One final Ada quibble: Why are Ada generics so static? Generics would be far more powerful, without being less safe(?), if the *instantiations* were compiled statically, rather than the generic itself. Chris.