C625 Project Covariant Return Types Group 5 members: Irene Cheng Nicholas Lamb Wesley Mackay...
-
date post
22-Dec-2015 -
Category
Documents
-
view
214 -
download
0
Transcript of C625 Project Covariant Return Types Group 5 members: Irene Cheng Nicholas Lamb Wesley Mackay...
C625 Project
Covariant Return Types
Group 5 members:
Irene Cheng
Nicholas Lamb
Wesley Mackay
December 4th, 2002
Overview
• Motivation
• Project Objective
• Design & Implementation
• Test example
• Conclusions & Future Work
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 error-prone
Current Java Return Mechanism
Vector
Object elementAt(int)Object firstElement()Object lastElement()
PointVector
ObjectObjectObject
elementAt(int)firstElement()lastElement()
Invariant return type
Better Return Mechanism
Vector
Object elementAt(int)Object firstElement()Object lastElement()
PointVector
PointPointPoint
elementAt(int)firstElement()lastElement()
Covariant return type
Coding Example
• In current Java, we must use PointVector as follows:
Point origin(0,0);PointVector shapePts = new PointVector();
shapePts.addElement( new Point(1,1) );shapePts.addElement( new Point(2,-5) );shapePts.addElement( new Point(-3,0) );
// 2nd argument requires an explicit // cast, which is costly and confusing
distanceBetween(origin, (Point) shapePts.firstElement() );
Coding Example
• With covariant return types, we could use PointVector as follows:
Point origin(0,0);PointVector shapePts = new PointVector();
shapePts.addElement( new Point(1,1) );shapePts.addElement( new Point(2,-5) );shapePts.addElement( new Point(-3,0) );
// 2nd argument does not require casting,// making code simpler and safer
distanceBetween(origin, (Point) shapePts.firstElement() );
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 methods defined in class hierarchies
• Phase 2
Apply concept of covariance to primitive return types
• Phase 3
Extend the above capabilities to interface methods
ClassD
public ClassA foo();
ClassE
public ClassB foo();
ClassF
public ??? foo();
Phase 1 - Type Checking Mechanism
ClassA
ClassB ClassC
What return types should be allowed?
ClassD
public ClassA foo();
ClassE
public ClassB foo();
ClassF
public ClassC foo();
Design option 1 – Check against top level
ClassA
ClassB ClassC
Covariant only against the top-level
declaration
ClassD
public ClassA foo();
ClassE
public ClassB foo();
ClassF
public ClassC foo();
Problem – Context Dependent
ClassA
ClassB ClassC
Covariant rules broken by the removal
of ClassD
ClassD
public ClassA foo();
ClassE
public ClassB foo();
ClassF
public ClassB foo();
Design option 2 – Check against next level
ClassA
ClassB ClassC
Covariant model always maintained at
all levels
ClassD
public ClassA foo();
ClassE
public ClassB foo();
ClassF
public ClassB foo();
Design option 2 – Check against next level
ClassA
ClassB ClassC
Covariant model preserved when ClassD
is removed
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
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 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
InterfaceA
public short foo() {…}
InterfaceB
public float foo() {…}
ClassC implements InterfaceA, InterfaceB
public ??? foo() {…}
• We could not define such a ClassC in conventional Java because it would be impossible to satisfy both interfaces
Phase 3 - Example of interfaces
InterfaceA
public short foo() {…}
InterfaceB
public float foo() {…}
ClassC implements InterfaceA, InterfaceB
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
InterfaceA
public boolean foo() {…}
InterfaceB
public float foo() {…}
ClassC implements InterfaceA, InterfaceB
public ??? foo() {…}
• Implementing multiple interfaces can still fail if there’s no common covariant type
Test Example
class ClassX {
ClassA classTest(Object o) { ClassA obj = new ClassA(0); return obj; }}
interface interfaceI { public int alpha(int a, int b);}
interface interfaceJ { public ClassC theta(float e);}
Test Example
class ClassY extends ClassX implements interfaceI, interfaceJ { ClassD classTest(Object o) { ClassD obj = new ClassD(0); return obj; }
public double alpha(int a, int b) { return 0; }
public ClassB theta(float e) { return new ClassB(12); }
Sample Output - Invalid return types
JVM Warning Messages:
Warning: In method ClassA::alpha(II)DD is not an assignment subtype of I
Warning: In method ClassY::theta(F)LClassB;LClassB is not an assignment subtype of LClassC
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