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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 1108a1,c52c30d32b866eae X-Google-Attributes: gid1108a1,public X-Google-Thread: 103376,2ea02452876a15e1 X-Google-Attributes: gid103376,public From: cjames@melchizedek.cec-services.com (The Right Reverend Colin James III) Subject: Re: Real OO Date: 1996/03/18 Message-ID: <314d98bf.562645731@news.dimensional.com> X-Deja-AN: 143043769 references: <4id031$cf9@dayuc.dayton.saic.com> <4ik3j7$cl6@watnews1.watson.ibm.com> organization: CEC Services, LLC reply-to: cjames@melchizedek.cec-services.com newsgroups: comp.lang.ada,comp.object Date: 1996-03-18T00:00:00+00:00 List-Id: ncohen@watson.ibm.com (Norman H. Cohen) posted with deletions: | In article <4id031$cf9@dayuc.dayton.saic.com>, John G. Volan | writes (concerning the division of a | tagged type's interfaces into multiple subinterfaces for different | clients): | | |> Here's an alternative approach that is subtly -- but significantly -- | |> different: Make the subprograms in the child packages _classwide_ | |> operations, and have them _dispatch_ to the private primitives: | |> | |> package Abstraction_1 is | |> type T is tagged null record; | |> private | |> procedure Op_1 (X: in out T); -- for Specialty_1 | |> procedure Op_2 (X: in out T); -- for Specialty_2 | |> end Abstraction_1; | |> | |> | |> package Abstraction_1.Specialty_1 is | |> procedure Op_1 (X: in out T'Class); -- classwide operation | |> pragma Inline (Op_1); | |> end Abstraction_1.Specialty_1; | |> | |> package body Abstraction_1.Specialty_1 is | |> procedure Op_1 (X: in out T'Class) is | |> begin | |> Abstraction_1.Op_1 (X); -- dispatching call | |> end Op_1; | |> end Abstraction_1.Specialty_1; | ... | |> package Abstraction_1.Specialty_2 is | |> procedure Op_2 (X: in out T'Class); -- classwide operation | |> pragma Inline (Op_2); | |> end Abstraction_1.Specialty_2; | |> | |> package body Abstraction_1.Specialty_2 is | |> procedure Op_2 (X: in out T'Class) is | |> begin | |> Abstraction_1.Op_2 (X); -- dispatching call | |> end Op_2; | |> end Abstraction_1.Specialty_2; | | Yes, this is an excellent paradigm! Extending T means that there is more | than one kind of T, but that the two subinterfaces are designed to | perform particular functions with any kind of T that comes along. The | fact that there is more than one kind of T is irrelevant to the users of | these packages, as long as Op_1 or Op_2 does the appropriate thing for | any kind of T that is encountered. Defining "the right thing" is the | responsibility of the programmer extending T. | | ... | |> (In fact, I'd say in general that any operation ought to be classwide if | |> it isn't explicitly a primitive. IMHO, only under very rare | |> circumstances should a non-primitive operation restrict a parameter to | |> accept only a specific root type but not any of its derived types.) | | By instinct, I'm wary of such sweeping generalizations. However, it | would appear that John's approach is the appropriate one in many | circumstances. | | ... | |> (Well, this whole discussion might be a lot clearer if we had a more | |> concrete example that exhibited this kind of pattern. Ideas anyone?) | | My canonical example of an abstraction that has different interfaces for | different clients is a device driver, or more precisely, an abstract | device state. There are certain operations meant to be invoked from | interrupt handlers as the result of events in a device; there are other | operations meant to be invoked from application programs using the | device. | | One can define an abstract tagged type for device states, together with | dispatching operations, in a parent package. Separate child packages, | one providing an interface for interrupt handlers and one providing an | interface for applications, can define classwide versions of those | operations appropriate for each interface. These classwide versions | simply invoke the corresponding dispatching operation of the abstract | tagged type. | | For each kind of phyiscal device, one derives from the abstract type, | overriding all its operations. Given an object corresponding to a | particular kind of physical device, a client (either an interrupt handler | or an application) continues to simply invoke the corresponding classwide | operation, which dutifully makes a dispatching call that dispatches to | the overriding subprogram defined for the appropriate derived type. This | isolates clients from the details of physical devices and makes it | unnecessary to modify clients when new physical devices arise. | | (Of course a new physical device may make a new kind of abstract | operation possible. This will be defined as a primitive operation of the | corresponding derived type. Children of the packages providing | interrupt-handler and client interfaces can provide corresponding | classwide operations for use by clients.* Thus application clients CAN be | modified to take advantage of the special characteristics of a new | physical device, as a result of a deliberate decision to upgrade the | application. However, this is not NECESSARY: A client that was working | before the new physical device was added will continue working, so the | client can be upgraded at our leisure or not at all.) | | *-To avoid the need for clients to become aware of whether a given | abstract device supports the new operation, the classwide operation | should accept a parameter of the classwide type of the original root | abstract type and check whether the object belongs to a class for which | dispatching is possible. If not, the classwide type should provide an | appropriate response--perhaps an expensive emulation of the new | operation using the old operations common to all devices. | | -- | Norman H. Cohen ncohen@watson.ibm.com This has nothing to do with Eiffel, does it. So stop distributing your inane thread to comp.lang.eiffel. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Colin James III, Principal Scientist cjames@cec-services.com CEC Services, 2080 Kipling St, Lakewood, CO 80215-1502 USA Voice: 303.231.9437; Facsimile: .231.9438; Data: .231.9434 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~