In Java,
interface Shape<T> {
interface _Circle<T> {
T apply(int x, int y, int r);
}
interface _Rectangle<T> {
T apply(int x, int y, int w, int h);
}
T apply(_Circle<T> circle, _Rectangle<T> rectangle);
static <T> Shape<T> Circle(int x, int y, int r) {
return (circle, rectangle) -> circle.apply(x, y, r);
}
static <T> Shape<T> Rectangle(int x, int y, int w, int h) {
return (circle, rectangle) -> rectangle.apply(x, y, w, h);
}
static double area(Shape<?> shape) {
var s = (Shape<Double>) shape;
return s.apply(
(x, y, r) -> Math.PI * r * r,
(x, y, w, h) -> 1. * w * h
);
}
static void main(String[] args) {
var exampleCircle = Circle(2, 1, 4);
var exampleRectangle = Rectangle(1, 3, 10, 7);
System.out.println(area(exampleCircle));
System.out.println(area(exampleRectangle));
}
}
BTW, you can use the same encoding when you write a Promise in JS.