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: fac41,c52c30d32b866eae X-Google-Attributes: gidfac41,public X-Google-Thread: 1108a1,c52c30d32b866eae X-Google-Attributes: gid1108a1,public X-Google-Thread: 103376,2ea02452876a15e1 X-Google-Attributes: gid103376,public From: jsa@organon.com (Jon S Anthony) Subject: Re: Real OO Date: 1996/04/30 Message-ID: X-Deja-AN: 152133941 sender: news@organon.com (news) references: organization: Organon Motives, Inc. newsgroups: comp.lang.eiffel,comp.lang.ada,comp.object Date: 1996-04-30T00:00:00+00:00 List-Id: In article donh@syd.csa.com.au (Don Harrison) writes: > :>a) a type has been redefined to a non-conformant type, or > :>b) a routine has been made inaccessible due to a change in it's export status. > :> > :>At first sight, it seems silly to permit such things if they can > :>cause problems with polymorphism but there is a worthy motivation for > :>providing such flexibility: > :> > :>allowing reuse of legacy code that does not exactly fit your requirements. > :^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > :I don't quite follow this. It does not seem to have much of anything > :to do with the problem of system validity checks. I suppose you can > :claim that overiding export policies and making covariant routine > :signatures (I think you mean conforming, not non-conforming) is > :is necessary to the emphasized goal, but I don't see it. > > Yes, I was wrong. It should be conforming signatures, as you say. (I > was trying to avoid looking it up). A good example illustrating both > a) and b) is in ETL, 22.6 - Notes on the type policy. > >[Eiffel example snipped] > > : This goal is > :trivial to achieve in Ada, do in large part to separation of > :specifications (interfaces) and implementations (yeah, that old > :argument). Add to this separation of interface and implementation > :inheritance, and these problems disappear. > > Can you explain how these avoid the problem? First, this is a really bad design (even for an example) as it violates any of the (several) reasonable definitions of is-a semantics. Second, this example has nothing to do with "legacy" code or reuse (which is what you claimed was important and I was refering to). But, let's take it at face value. Neither the a) no b) case is a problem - not even an issue - in Ada. This is mainly due to the separation of specific and classwide types. The example in Ada: package Drivers is type Driver is tagged private; ... end Drivers; package Drivers.Cars is type Car_Driver is new Driver with private; ... end Drivers.Cars; package Drivers.Trucks is type Truck_Driver is new Driver with private; ... end Drivers.Trucks; with Drivers; use Drivers; package Vehicles is type Vehicle is tagged private; procedure Register_Driver (V: Vehicle; D: Driver); procedure Renew_Rego_By_Mail (V: Vehicle); ... end Vehicles; with Drivers.Cars; use Drivers.Cars; package Vehicles.Cars is type Car is new Vehicle with private; procedure Register_Driver (V: Vehicle; D: Car_Driver); ... end Vehicles.Cars; with Drivers.Trucks; use Drivers.Trucks; package Vehicles.Trucks is type Truck is new Vehicle with private; procedure Register_Driver (T: Truck; D: Truck_Driver); procedure Renew_Rego_By_Inspection(T: Truck); ... end Vehicles.Trucks; -- In a client somewhere -- D: Driver; Cd: Car_Driver; V: Vehicle; T: Truck; ... -- Option 1. -- D := Cd; -- Illegal, compile time error V := T; -- Illegal, compile time error -- Option 2. -- D := Driver(Cd); -- OK, convert toward root V := Vehicle(T); -- OK, convert toward root Register_Driver(V, D); -- just fine and no dispatch needed -- Option 3. -- Register_Driver(Vehicle'Class(T),Cd); -- Compile error, no primitive ops -- Option 4. -- Register_Driver(Truck'Class(T), Cd); -- Compile error, no primitive ops -- Option 5. -- Register_Driver(Car'Class(T), Cd); -- Compile error, trucks not in -- Car'Class -- Option 6. -- Register_Driver(Vehicle'Class(V), D); -- Fine Register_Driver(Vehicle'Class(T), D); -- Fine (calls inherited op!!) As you can see, you can't get the invalid system stuff in the Ada model. In particular, you should note that the Truck type has _two_ primitive operations Register_Driver: procedure Register_Driver(V: Truck; D: Driver); -- Inherited from Vehicle procedure Register_Driver(V: Truck; D: Truck_Driver); -- *New* primitive op WRT b), note that in Ada, you cannot remove operations from derived types - they can always be used in any context where a parent can be used. To achieve this sort of effect, you would need to define Truck differently: package Vehicles.Trucks is type Truck is tagged private; -- Interface indicates new type procedure Register_Driver (T: Truck; D: Truck_Driver); procedure Renew_Rego_By_Inspection(T: Truck); ... end Vehicles.Trucks; Lastly, if you really wanted to do an a) like thing, a _client_ could define the exact semantics of it so that it "works" (at least to the extent that the client i) knowingly forced the issue, ii) had to supply semantics that did not violate the rules, and iii) knows what he's doing...) For example, -- in client... -- procedure Register_Driver (V: Vehicle'Class; D: Driver'Class) is -- -- Eats anything... ... begin ... if V in Truck'Class and not D in Truck_Driver'Class then -- -- Do something "appropriate"... Hope I know what I'm doing! ... elsif V in Car'Class and not D in Car_Driver'Class then -- -- Similar special sort of stuff... else -- Register_Driver(V, Driver(D)); end if; ... end Register_Driver; > :> for runtime. (Yes, I know that few, if any, Eiffel vendors implement > :> it). Don't know what you mean here. > : > :I mean simply that invalid Eiffel systems are knowingly accepted by > :these implementations. > > Correct. Note that this does _not_ happen in the Ada case and you loose no "flexibility" or what-have-you. In fact the Ada model seems to be significantly more flexible (this is not surprising as you have more semantic information to work with!) > :> : And the reason it is a problem > :> :is that Eiffel source does not have as much semantic information in it > :> :in this area. > :> > :> What might that be? > : > :Specifically, the distinction and use of the difference between class > :and type. The funny thing is, all this brouhaha about system validity > :concerns this distinction and an attempt to try to separate them > :again. > > No. This is not why. It's due to the distinction between static and dynamic > types. Hmmm, Meyer seems to disagree: ETL 22.4 (System Level Validity) "...but with generic derivation, expansion and anchored types we will need to reintroduce the distinction between types and classes." > : Meyer's "dynamic type set" is pretty much an Ada class and his > :"dynamic class set" is pretty much a class-wide type. > > No. There is not really an equivalent concept in Ada because it does not > support generic tagged types (as far as I'm aware) or anchored types. Sure it does, and as for anchored - they are _subsumed_ by classwide types > The dynamic type set is the set of all possible dynamic types whereas the > dynamic class set is the set of all classes these are derived from. > A generic class in the dynamic class set becomes numerous types in the > dynamic type set. I didn't say they were _identical_ concepts, I was trying to point out some similarity so that you might notice that basically, in Ada, the two concepts are made explicit in the notion of classwide types. For a given specific type T, T'Class is defined at the set of types rooted at T in a type derivation tree. If we have an object X : T'Class := some_value; X can take on any value of any type in T'Class (including T'Class). This also holds in the case of generic formals. That pretty much covers all that can be said about dynamic type/class sets. It's really very nice to be able to explicitly have control over how, where, and when these things are used. /Jon -- Jon Anthony Organon Motives, Inc. 1 Williston Road, Suite 4 Belmont, MA 02178 617.484.3383 jsa@organon.com