class Pt extends Object { float x; float y; boolean isXPos(Pt p) { return p.x > 0; } Pt(float _x, float _y) { x = _x; y = _y; } } class Pt3D extends Pt { float z; Pt3D(float _x, float _y, float _z) { super(_x,_y); z = _z; } } class C extends Object { void f(Pt3D p1, Pt p2) {} void f(Pt p1, Pt3D p2) {} void g(Pt3D p1, Pt3D p2) { // f(p1,p2); // no best match! f(p1,(Pt)p2); // fine with static overloading } } // 3 casts just to use composition using interface I interface I { Object apply(Object o); } class Compose implements I { I f; I g; public Object apply(Object o) { return g.apply(f.apply(o)); } Compose(I _f, I _g) {f = _f; g = _g;} } class A1 implements I { public Object apply(Object o) { return apply((Pt) o); } public Pt3D apply(Pt p) { return new Pt3D(p.x, p.y, 0);} } class A2 implements I { public Object apply(Object o) { return apply((Pt3D) o); } public Pt apply(Pt3D p) { return new Pt(p.x, p.y); } } class A3 { void f() { I copyPoint = new Compose(new A1(), new A2()); Pt p = (Pt) copyPoint.apply(new Pt(3,4)); } }