🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.eiffel
Article #1280

Re: Conflict Between Class-as-Module and Class-as-Type (long)

#1280
From: Jos Warmer
Date: Tue, 10 Jan 1989 08:53
111 lines
4724 bytes
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
Technical Details
Message-ID: <1884@vlot.cs.vu.nl>
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!jos
References: <6417@bunny.UUCP>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!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