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: border2.nntp.ams.giganews.com!nntp.giganews.com!newsfeed.fsmpi.rwth-aachen.de!news-1.dfn.de!news.dfn.de!news.informatik.hu-berlin.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: Your wish list for Ada 202X Date: Fri, 18 Apr 2014 22:59:26 +0300 Organization: Tidorum Ltd Message-ID: References: <7f1c01c5-3563-4b94-9831-152dbbf2ecdc@googlegroups.com> <8bhozh836pyt$.1qctlysud0s2q$.dlg@40tude.net> <1cdsyxjzsfgzm.1synpaujysv21$.dlg@40tude.net> <1aa804jg9qq4o$.wdiq33yo621l.dlg@40tude.net> <1w6eh0aiksmdh$.1h16p7y0b8c6h.dlg@40tude.net> <17twpp4p8u7o$.1idvzaaio4f3t$.dlg@40tude.net> <1wjmcbk375lzk.6o7dpqcp3va3.dlg@40tude.net> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: individual.net fhLuiXlCGbO7vG8I7DwpCQjrG5tgL4ngi4LG8oAoodHxDUAiD/ Cancel-Lock: sha1:4jhxgBJ7qWTkq9WtSdEADa5nZyQ= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 In-Reply-To: Xref: number.nntp.dca.giganews.com comp.lang.ada:185816 Date: 2014-04-18T22:59:26+03:00 List-Id: On 14-04-17 01:27 , Randy Brukardt wrote: > "Niklas Holsti" wrote in message > news:br8bu5Fg3keU1@mid.individual.net... >> On 14-04-15 03:08 , Randy Brukardt wrote: > ... >>> Dispatching operations necessarily have weaker contracts than statically >>> bound calls, and that is especially important for "contracts" that can't >>> be >>> described in Ada and thus can't be checked (either statically or >>> dynamically). >> >> Hm, I'm not convinced of that. To me, the informal contract for a >> dispatching operation Foo is "implements the Foo operation as specified >> for the class and as appropriate for the actual type". Of course these >> specifications are given in comments. > > A lot of our discussion has become subjective, and I don't know if there is > a lot to be learned comparing somewhat different world-views. So I'm only > going to respond to a couple of points here... > > Anyway, there is two problems with "specifications given in comments": Sorry, I think you misunderstood: I was replying to the case which you described as "contracts that can't be described in Ada". I fully agree that formal contracts are preferable to informal ones, no argument. I don't (yet) use formal contracts, however, except for those that Ada provides implicitly. >> I don't see the "necessarily ... weaker" for the more formal contracts >> either. Yes, for a dispatching call there are more possible callee >> operations (implementations) to check against the contract, but the >> general contract (as experienced by the caller) can be the same for all. > > LSP says that preconditions have to combine weaker in order for dispatching > calls to make sense. Weaker *or equal*, I think. > Whether LSP is really the last word on OOP is an open > question, but if you mean to follow it, at least part of the contract *has* > to be weaker in a dispatching call. Why can't it be equal, again from the point of view of the caller? The full contract for the operation on a derived type is indeed stronger in the sense that it says something specific about the derived type, for example about changes in the components added in the derivation. But those details are not important to the caller's point of view; only the contract's effects on the higher level (caller's type) are relevant. For example, if we have a class of "file" types, with different derived types implementing files on different kinds of storage devices, and a dispatching call of Open, the changes in the device-specific components of the file object are not relevant to the caller of Open; it is only relevant that the file's class-level status changes from "closed" to "open". > There's also the point that a > dispatching call always has to be assumed to be to some body not even > written yet, so it's nearly impossible to say anything definitive about it's > contract. But the operation has been *specified*, even if no bodies exist, therefore the contract *from the caller's point of view* should have been defined. Otherwise there is not much point in using a class at all, or indeed in separating operation declarations and bodies. > ... >>> This last issue doesn't arise for a class-wide operation, where every >>> call is going to look at an object of TT as type TT. >> >> Except if TT inherits some operation from T, because then that operation >> looks at the object as type T. (I know that from the language-semantics >> point of view the inherited operation acts on TT, but the programmer >> wrote its code with T in mind.) >> >> If redispatching is suspect because it breaks the assocation of an >> operation with a unique type, then inheritance of operations must also >> be suspect, for the same reason. > > I understand your point, but I think the language-semantics view is actually > the correct one. One only allows inheritance of operations when the > implementation for T and for TT is thought to be identical. One hopes that > the author of TT considered that carefully! Well, I use redispatching only when I think that the operation being called is well specified and is or will be carefully implemented for each type in the class, as appropriate for that type. Same difference :-) > It's true that maintenance of the T operation might in fact break the TT > operation (meaning that they should have different implementations), so > there is some additional danger in inheritance. Yes. In general, the more a program is "factored" into parts that are combined and invoked in many contexts, the harder it becomes to maintain proper behaviour in all contexts. Subprograms, inheritance, dispatching, redispatching all tend in this direction. > There is also danger in > inheritance that the author of TT didn't know about. (I think it would be > much better if all inheritance was explicit; but to be practical that would > require a rather different syntax than Ada uses, and thus such a thing would > not make sense in an Ada perspective. To make inheritance explicit, it seems to me that each inherited operation must be declared for the derived type, with its full profile, perhaps as inherited procedure Foo (X: in T; ....); This would require just one new reserved word, "inherited", and does not feel like a "rather different syntax". Did you have something else in mind? > > I suppose one could forbid both inheritance and redispatching. That >> would be a major departure from traditional object/class-oriented >> programming. > > Not forbid so much as "require declaration of". Ada already does that for > redispatching; my opinion is that it should be used rarely, but as with all > such tools (e.g. goto), rarely is certainly not never. Thanks for explaining your view. I think I understand it now. > Twisting a design around to avoid redispatching is not likely to > improve anything. Agreed. As I said in my last reply to Dmitry, reaching this point was my reason for commenting on redispatching. I'm content to end here. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .