1 / 21

A Typeful Approach to Object-Oriented Programming with Multiple Inheritance

This paper explores a typeful approach to object-oriented programming with multiple inheritance, providing a sound typing system and modeling the basic features of OOP. The paper also introduces wrapper functions and super functions to implement multiple inheritance.

braun
Télécharger la présentation

A Typeful Approach to Object-Oriented Programming with Multiple Inheritance

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. A Typeful Approach to Object-Oriented Programming with Multiple Inheritance Chiyan Chen, Rui Shi, Hongwei Xi Computer Science Dept. Boston University PADL04

  2. Motivation • Through translating high-level OOP syntax to a typed -calculus, the soundness of the typing rules for the OOP features follows from the soundness of the target system. • Within the Applied Type System (ATS) framework, we want to support OOP as an additional package without complicating the existing system. PADL04

  3. Objects as Functions • Examples: Smalltalk • Interpretation: An object is represented as a message interpreter, that is, a function which takes messages dispatched to it as arguments and then selects the appropriate behavior according to the messages. • Message passing: function application. PADL04

  4. Constructing an Integer Pair Object • fun newIntPair x y = let val xref = ref x and yref = ref y fun dispatch msg = case msg of | MSGgetfst => !xref | MSGgetsnd => !yref | MSGsetfst x' => (xref := x') | MSGsetsnd y' => (yref := y') | _ => raise UnknownMessage in dispatch end withtype int -> int -> OBJ(ip) • Given a class C, OBJ(C) is a shorthand for the following type: :type.MSG(C,) →  PADL04

  5. Typed OOP Model • An improved typed OOP model based on the previous work (POPL’03, Xi, Chen and Chen) • Takes the “objects as functions” view • Models the basic features: message passing, single inheritance. • Provides a natural solution to the notion of “self type”. • Subclassing is modeled with explicit proof terms. • Supports multiple inheritance PADL04

  6. Single Inheritance vs.Multiple Inheritance • Single Inheritance: • Examples: Smalltalk, Java • Easy to reason and implement. • Multiple Inheritance: • Examples: Eiffel, C++ • Complicated model • Interaction with other OO features PADL04

  7. Subtlety with MI in C++ A :: foo() = 0 A B1 :: foo() = 1 B1 :: bar1() = foo() B2 :: foo() = 2 B2 :: bar2() = foo() B1 B2 C :: foo() = 3 C C* pc = new C(); pc->bar1() returns 3 PADL04

  8. Subtlety with MI in C++ A :: foo() = 0 A B1 :: foo() = 1 B1 :: bar1() = foo() B2 :: foo() = 2 B2 :: bar2() = foo() B1 B2 foo() is not overridden. C C* pc = new C(); pc->bar1() returns 1 PADL04

  9. Subtlety with MI in C++ A :: foo() = 0 A B1 :: foo() = 1 B1 :: bar1() = foo() B2 :: foo() = 2 B2 :: bar2() = foo() B1 B2 C :: bar3 () = B1 :: foo() D* pd = new D(); pd->bar3() returns 1 C D :: foo() = 4 D PADL04

  10. Subtlety with MI in C++ A :: foo() = 0 A B1 :: foo() = 1 B1 :: bar1() = foo() B2 :: foo() = 2 B2 :: bar2() = foo() B1 B2 C :: foo () = B1 :: foo() D* pd = new D(); pd->bar2() returns 1 C foo() is not overridden. D PADL04

  11. Our Solution • Using explicit inheritance paths to direct method lookup. A :: foo() = 0 A B1 :: foo() = 1 B1 :: bar1() = A :: B1 :: foo() B2 :: foo() = 2 B2 :: bar2() = A :: B2 :: foo() B1 B2 C :: bar3 () = A :: B1 :: C :: foo() C D* pd = new D(); pd->C :: D :: bar3() returns 4 D :: foo() = 4 D PADL04

  12. Run-Time Class Tags • datasort cls = obj | eq | ip | cip | … • datatype ClS (cls) = | CLSobj (obj) | CLSeq (eq) | CLSip (ip) | CLScip (cip) | ... eq obj Ip cip PADL04

  13. Inheritance Paths • Paths from (super)classes to (sub)classes are treated as run-time proof terms (of subclass relation) • DeclarePTH as a guarded datatype, which takes two static class tags C1 and C2 to form a type PTH(C1, C2) for paths from C1 to C2 • E.g. Abbreviate a path from class objto cip as [CLSobj, CLSip, CLScip] PADL04

  14. Regular/Temporary Objects • Given a static class tag C, OBJ(C) is the type for regular objects in class C, whichis the shorthand for the following type: c0:cls.:type.PTH(c0,C) → MSG(c0,C,) → • There is another form of objects that are only constructed during run-time calledtemporary objects. Given a static class tag C, OBJ0(C)stands for the type: c0:cls. :type.MSG(c0,C,) → • Note that a temporary object is not constructed by applying a regular object to a given path. PADL04

  15. Wrapper Functions • A wrapper function for a class C is assigned the type WRP(C), where WRP(C) stands for the following type: OBJ(C) → OBJ0(C) • Intuitively, a wrapper function turns a regularobject in class C into a temporary object in class C. • A wrapper function is mainly used to “hard-wire” a method lookup strategy into a regular object. PADL04

  16. Super Functions • For each class C, there is a super function associated with it, which plays a key role in implementing (multiple) inheritance. • Given a static class tag C0, the super function associated with C0is assigned the typeSUPER(C0), which is the shorthand for the following type: c:cls.PTH(C0,c) → WRP (c) → WRP (c) PADL04

  17. An Example of Super Function • fun SUPEReq pth wrp obj = let fun dispatch msg = case msg of | MSGeq (obj') => not (obj pth (MSGneq (obj'))) | MSGneq (obj') => not (obj pth (MSGeq (obj'))) | _ => wrp obj msg in dispatch end withtype {c:cls} PTH (eq,c) → WRP(c) → WRP (c) PADL04

  18. Chaining Super Functions Together • Given an object o, nullwrapper(o) constructs a temporary object, which raises the UnknownMessage exceptionfor any message received. • Given a run-time inheritance path p, path2wrapper(p) turns the path to a wrapper. e.g. path2wrapper [CLSobj, CLSip, CLScip] = SUPERcip [CLScip] (SUPERip [CLSip, CLScip] (SUPERobj [CLSobj, CLSip, CLScip] nullWrapper)) PADL04

  19. Constructing Objects • newintPair is an object constructor function, which takes two integers to create an integer pair object. • fun newIntPair x y = let val xref = ref x and yref = ref y fun dispatch pth msg = case msg of | MSGcopy => newIntPair (!xref) (!yref) | MSGgetfst => !xref | MSGsetfst x' => (xref := x') | … | _ => path2wrapper pth dispatch msg in dispatch end withtype int -> int -> OBJ (ip) PADL04

  20. Example for Method Lookup • Given two integer pair objects o1 and o2, let us consider No message handler for MSGneq(o2) [CLSeq, CLSip] (MSGneq(o2)) O1 path2wrapper[CLSeq, CLSip] o1 (MSGneq(o2)) No message handler for MSGneq(o2) SUPERip [CLSip] (SUPEReq [CLSeq, CLSip] nullWrapper) o1 (MSGneq(o2)) MSGeq(o2) finally be handled by SUPERip Has message handler for MSGneq(o2) (SUPEReq [CLSeq, CLSip] nullWrapper) o1 (MSGneq(o2)) [CLSeq, CLSip] (MSGeq(o2)) not O1 PADL04

  21. Conclusion • We have developed a general approach to multiple inheritance in a typed setting • Representing inheritance paths as (typed) run-time proof-terms. • Different strategies to resolve dispatching ambiguity • Interaction between multiple inheritance and parametric polymorphism • A clear model which can be implemented efficiently (e.g. by following C++ implementation) PADL04

More Related