Path: utzoo!attcan!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!jos From: jos@cs.vu.nl (Jos Warmer) Newsgroups: comp.lang.eiffel Subject: Re: Conflict Between Class-as-Module and Class-as-Type (long) Message-ID: <1884@vlot.cs.vu.nl> Date: 10 Jan 89 08:53:37 GMT References: <6417@bunny.UUCP> Reply-To: jos@cs.vu.nl (Jos Warmer) Organization: VU Informatica, Amsterdam Lines: 111 In article <6417@bunny.UUCP> dcr0@bunny.UUCP (David Robbins) writes: > >I have three classes named ROOT_CLASS, A, and B, defined as follows: > > class ROOT_CLASS > inherit STD_FILES > feature > an_a: A; a_b: B; b_invoked_as_a: A; > Create is do > an_a.Create; a_b.Create; b_invoked_as_a := a_b; > putstring("Calling A.f1: "); an_a.f1; > putstring("Calling A.f2: "); an_a.f2; > putstring("Calling B.f2: "); a_b.f2; > putstring("Calling B.f3 (which is really A.f1): "); a_b.f3; > putstring("Calling B.f1 through A's interface: "); b_invoked_as_a.f1; > putstring("Calling B.f2 through A's interface: "); b_invoked_as_a.f2 > end > end > > class A export f1, f2 > inherit STD_FILES > feature > f1 is do putstring("I am A.f1"); new_line end; > f2 is do putstring("I am A.f2"); new_line end > end > > class B export f2, f3 > inherit A rename f1 as f3 redefine f2 > feature > f2 is do putstring("I am B.f2"); new_line end > end > >Results of Execution -- > > Calling A.f1: I am A.f1 > Calling A.f2: I am A.f2 > Calling B.f2: I am B.f2 > Calling B.f3 (which is really A.f1): I am A.f1 > Calling B.f1 through A's interface: I am A.f1 > Calling B.f2 through A's interface: I am B.f2 > >export f1. Since B does not export f1, I would certainly not expect >"b_invoked_as_a.f1" to succeed. After all, it is trying to call feature f1 >of an instance of B, which does not export any such feature. In fact, B >does not even possess a feature named f1! > This behaviour is correctly defined in eiffel. It is even neccesary to define this behaviour if you want compile-time checking. The entity "b_invoked_as_a" has static type A. It is impossible for the compiler to know the dynamic type of "b_invoked_as_a". So if the compiler has to check whether some feature is applicable to "b_invoked_as_a", it can only look at the features of A. If a feature is not redefined, then the definition from A is used. This choice can only be made at runtime. The rules are: The features that may be applied to an entity depend on the static type of the entity. The actual definition used may depend on the dynamic type. The call "b_invloked_as_a.f3" will not be allowed by the compiler, because it is not exported by class A. This behaviour can also be undesirable when using implementation inheritance, as I stated in a previously posted article. ++ At page 241 of Bertand Meyer's book an alternate definition is ++ given for STACK2 (page 118): the class FIXED_STACK. It is declared ++ an heir of class ARRAY, instead of a client. ++ ++ As far as I can see this definition of FIXED_STACK has a serious ++ safety-leak, as opposed to the definition of STACK2 at page 118. ++ ++ Consider the following piece of (pseudo) eiffel code: ++ ++ a : ARRAY[INTEGER]; -- declare an entity of type ARRAY ++ f : FIXED_STACK[INTEGER]; -- declare an entity of type FIXED_STACK ++ ++ f.Create; -- created a fixed stack ++ f.push(12); -- top of stack is now 12 ++ ++ a := f; -- allowed, because FIXED_STACK is descendant of ARRAY ++ a.enter(1, 20); -- enter is allowed on ARRAY's ++ ++ value := f.top: -- this will deliver value 20, instead of the previously ++ -- entered 12. ++ ++ This example shows that any client of FIXED_STACK can manipulate its ++ implementation. >This behavior violates my expectation of what I tend to call "specification >inheritance." Inheritance in eiffel is always inheritance of the complete implementation. >counterexample to this claim: class B is totally unequipped to handle >feature f1 (although the Eiffel implementation manages to secretly give B a >feature named f1, in violation of the semantics of Eiffel). class B is a descendant of class A, so it IS equipped to handle feature f1. Jos Warmer jos@cs.vu.nl ...uunet!mcvax!cs.vu.nl!jos PS. We have ordered the compiler, but it hasn't arrived yet. So I can't try anything out. This is not too bad, now I actually have to *think* about it. -- Jos Warmer jos@cs.vu.nl ...uunet!mcvax!cs.vu.nl!jos