Given this java code:
public class Main {
public static void main(String[] args) {
// These are objects of the only 2 classes that implement Parent
// `sealed` defines that there can't be any other classes that implement Parent
Child1 child1 = new Child1();
Child2 child2 = new Child2();
// I can call myMethod(child1) and myMethod(child2) on myClass
MyInterface myClass = new MyClass();
myClass.myMethod(child1);
myClass.myMethod(child2);
// I can also call myMethod(child1) and myMethod(child2) on myInterface
MyInterface myInterface = new MyClass();
myInterface.myMethod(child1);
myInterface.myMethod(child2);
}
}
sealed interface Parent {}
record Child1() implements Parent {}
record Child2() implements Parent {}
interface MyInterface {
void myMethod(Parent parent);
}
// Why can't I override myMethod(Parent parent) with myMethod(Child1 child1) and myMethod(Child2 child2)?
// This should be exhaustive, since Parent is sealed and there can't be any other classes that implement Parent
class MyClass implements MyInterface {
//@Override
public void myMethod(Child1 child1) {
System.out.println("Child1");
}
//@Override
public void myMethod(Child2 child2) {
System.out.println("Child2");
}
// Why is this method needed after declaring the two methods above?
@Override
public void myMethod(Parent parent) {
if (parent instanceof Child1) {
myMethod((Child1) parent);
} else if (parent instanceof Child2) {
myMethod((Child2) parent);
}
}
}
(See also: https://gist.github.com/CC007/768973376ce4ebbfdd3482c5f1bf90b9)
Why can't I override a method with a sealed type (class/interface) as one of the parameters (see MyInterface
), by creating methods for the individual children of the sealed type? (see MyClass
).
If the Parent
interface wasn't sealed, I would understand that this implementation wouldn't guarantee to be exhaustive, but as a sealed type, there can't be any other child classes/records other than Child1
and Child2
.
So why can't I omit the myMethod(Parent parent)
method in MyClass
and why can't I define @Override
on the other 2 methods in MyClass
?
Why can't I override a method with a sealed type (class/interface) as one of the parameters (see
MyInterface
), by creating methods for the individual children of the sealed type? (seeMyClass
).
This is not the way Java works. According to the specification:
8.4.8.1. An instance method mC [...] overrides [...] another method mA [...], if all of the following are true: [...] The signature of mC is a subsignature (§8.4.2) [...].
8.4.2. Two methods [...] have the same signature if they have the same name, [...], and, [...] the same formal parameter types.
https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.4.8.1
One example of how Java sealed types work related to your example is pattern matching. You could write myMethod
as follows:
@Override
public void myMethod(Parent parent) {
switch (parent) {
case Child1 c -> System.out.println("Child1");
case Child2 c -> System.out.println("Child2");
//exhaustive because of sealed type
}
}