C 625 Project Covariant Return Types Group 5

  • Slides: 26
Download presentation
C 625 Project Covariant Return Types Group 5 members: Irene Cheng Nicholas Lamb Wesley

C 625 Project Covariant Return Types Group 5 members: Irene Cheng Nicholas Lamb Wesley Mackay December 4 th, 2002

Overview • Motivation • Project Objective • Design & Implementation • Test example •

Overview • Motivation • Project Objective • Design & Implementation • Test example • Conclusions & Future Work

Motivation • Return type of an overriding method must match return type of the

Motivation • Return type of an overriding method must match return type of the top-level declaration • This restriction simplifies the language but makes it inflexible • Type information can be lost • Casting can regain type information, but makes code less readable, slower and errorprone

Current Java Return Mechanism Vector Object element. At(int) Object first. Element() Object last. Element()

Current Java Return Mechanism Vector Object element. At(int) Object first. Element() Object last. Element() Invariant return type Point. Vector Object element. At(int) Object first. Element() Object last. Element()

Better Return Mechanism Vector Object element. At(int) Object first. Element() Object last. Element() Covariant

Better Return Mechanism Vector Object element. At(int) Object first. Element() Object last. Element() Covariant return type Point. Vector Point element. At(int) first. Element() last. Element()

Coding Example • In current Java, we must use Point. Vector as follows: Point

Coding Example • In current Java, we must use Point. Vector as follows: Point origin(0, 0); Point. Vector shape. Pts = new Point. Vector(); shape. Pts. add. Element( new Point(1, 1) ); shape. Pts. add. Element( new Point(2, -5) ); shape. Pts. add. Element( new Point(-3, 0) ); // 2 nd argument requires an explicit // cast, which is costly and confusing distance. Between(origin, (Point) shape. Pts. first. Element() );

Coding Example • With covariant return types, we could use Point. Vector as follows:

Coding Example • With covariant return types, we could use Point. Vector as follows: Point origin(0, 0); Point. Vector shape. Pts = new Point. Vector(); shape. Pts. add. Element( new Point(1, 1) ); shape. Pts. add. Element( new Point(2, -5) ); shape. Pts. add. Element( new Point(-3, 0) ); // 2 nd argument does not require casting, // making code simpler and safer distance. Between(origin, (Point) shape. Pts. first. Element() );

Project Objective • Add support for covariant return types to improve flexibility and maintainability

Project Objective • Add support for covariant return types to improve flexibility and maintainability • No changes to the JVM compiler • No impact on current invariant return type mechanism (backwards compatibility)

Design & Implementation • Phase 1 Add support for covariant return types to virtual

Design & Implementation • Phase 1 Add support for covariant return types to virtual methods defined in class hierarchies • Phase 2 Apply concept of covariance to primitive return types • Phase 3 Extend the above capabilities to interface methods

Phase 1 - Type Checking Mechanism Class. D Class. A public Class. A foo();

Phase 1 - Type Checking Mechanism Class. D Class. A public Class. A foo(); Class. E public Class. B foo(); Class. F public ? ? ? foo(); Class. B Class. C What return types should be allowed?

Design option 1 – Check against top level Class. D Class. A public Class.

Design option 1 – Check against top level Class. D Class. A public Class. A foo(); Class. E public Class. B foo(); Class. F public Class. C foo(); Class. B Class. C Covariant only against the top-level declaration

Problem – Context Dependent Class. D Class. A public Class. A foo(); Class. E

Problem – Context Dependent Class. D Class. A public Class. A foo(); Class. E public Class. B foo(); Class. F public Class. C foo(); Class. B Class. C Covariant rules broken by the removal of Class. D

Design option 2 – Check against next level Class. D Class. A public Class.

Design option 2 – Check against next level Class. D Class. A public Class. A foo(); Class. E public Class. B foo(); Class. F public Class. B foo(); Class. B Class. C Covariant model always maintained at all levels

Design option 2 – Check against next level Class. D Class. A public Class.

Design option 2 – Check against next level Class. D Class. A public Class. A foo(); Class. E public Class. B foo(); Class. F public Class. B foo(); Class. B Class. C Covariant model preserved when Class. D is removed

Phase 2 - Primitive Types Hierarchy • Concept of covariant return types can be

Phase 2 - Primitive Types Hierarchy • Concept of covariant return types can be applied to Java primitives because of widening conversions • Widening conversions offer a form of substitutability • Consider that an integer value is also a floating point value • We can safely return an int at any call site expecting a float without affecting program logic

Phase 2 - Primitive Types Hierarchy double float boolean long int char short byte

Phase 2 - Primitive Types Hierarchy double float boolean long int char short byte

Handling Arrays • Array return types require extra checking • We verify that the

Handling Arrays • Array return types require extra checking • We verify that the array’s element type is covariant and that the dimensions match • Suppose in the parent we have a method: int[][] omega(int i, float f); • Then in a subclass: int[] omega(int i, float f); double[][] omega(int i, float f); short[][] omega(int i, float f);

Phase 3 - Covariant Returns for Interfaces • The implementation of an interface method

Phase 3 - Covariant Returns for Interfaces • The implementation of an interface method can have a return type that is covariant to what is declared in the interface • Since a class can implement multiple interfaces, the return type of an interface method should be covariant to all interface methods with the same signature

Phase 3 - Example of interfaces Interface. A Interface. B public short foo() {…}

Phase 3 - Example of interfaces Interface. A Interface. B public short foo() {…} public float foo() {…} Class. C implements Interface. A, Interface. B public ? ? ? foo() {…} • We could not define such a Class. C in conventional Java because it would be impossible to satisfy both interfaces

Phase 3 - Example of interfaces Interface. A Interface. B public short foo() {…}

Phase 3 - Example of interfaces Interface. A Interface. B public short foo() {…} public float foo() {…} Class. C implements Interface. A, Interface. B public short foo() {…} • With our extension, we could return a short or a byte because either of these is covariant to both short and float

Phase 3 - Example of interfaces Interface. A Interface. B public boolean foo() {…}

Phase 3 - Example of interfaces Interface. A Interface. B public boolean foo() {…} public float foo() {…} Class. C implements Interface. A, Interface. B public ? ? ? foo() {…} • Implementing multiple interfaces can still fail if there’s no common covariant type

Test Example Class. X Class. A interface. I Class. B Class. Y Class. C

Test Example Class. X Class. A interface. I Class. B Class. Y Class. C interface. J Class. D Class. E

Test Example class Class. X { Class. A class. Test(Object o) { Class. A

Test Example class Class. X { Class. A class. Test(Object o) { Class. A obj = new Class. A(0); return obj; } } interface. I { public int alpha(int a, int b); } interface. J { public Class. C theta(float e); }

Test Example class Class. Y extends Class. X implements interface. I, interface. J {

Test Example class Class. Y extends Class. X implements interface. I, interface. J { Class. D class. Test(Object o) { Class. D obj = new Class. D(0); return obj; } public double alpha(int a, int b) { return 0; } public Class. B theta(float e) { return new Class. B(12); }

Sample Output - Invalid return types JVM Warning Messages: Warning: In method Class. A:

Sample Output - Invalid return types JVM Warning Messages: Warning: In method Class. A: : alpha(II)D D is not an assignment subtype of I Warning: In method Class. Y: : theta(F)LClass. B; LClass. B is not an assignment subtype of LClass. C

Conclusions & Future Work • Covariant return types increase language flexibility and reduces the

Conclusions & Future Work • Covariant return types increase language flexibility and reduces the need for casting • Offers backwards compatibility • The JVM’s treatment of ‘signature’ introduces problems when dispatching • Need to remove the return type from the signature string whenever two signatures are compared • Better to store the return type in a separate string, apart from the method arguments