Some findings regarding records, sealed types and switch expressions
Daniel Dietrich
cafebab3 at googlemail.com
Thu Aug 22 22:54:02 UTC 2019
Thank you, Brian.
I worked on the patterns-deconstruction branch.
I updated to the latest change-set on the records-and-sealed branch and did a re-test of the following findings:
> On 23. Aug 2019, at 00:01, Brian Goetz <brian.goetz at oracle.com> wrote:
>
>> 1) Questions (sealed)
>>
>> 1.1) Question: Do make generics in the permits section sense?
>>
>> I can’t find a use case. The example below is misleading for a user.
>>
>> // why restrict an implementation to specific generic types?
>> sealed interface A permits B<String> {}
>> class B<T> implements A
>>
>> A a = new B<>(1);
>
> The permits clause should be a list of _classes_, not of _types_. If the compiler accepts the above, that's a compiler bug.
>
class Test {
public static void main(String[] args) {
A a = new B<>(1);
}
}
// compiles
sealed interface A permits B<String> {}
record B<T>(T t) implements A {}
>> 1.2) Error: A generic sealed interface cannot be subclassed
>>
>> sealed interface A<T> permits B<T> {}
>> class B<T> implements A<T> {}
>>
>> sealed interface A<T> permits B {}
>> class B<T> implements A<T> {}
>>
>> sealed interface A<T> permits B {}
>> class B implements A {}
>>
>> In all three examples we get "cannot inherit from sealed class: A"
>
> I would expect the latter two sets of examples to work (the last example merely implements the raw type A, rather than the parameterized type A<T>.) This sounds like a bug.
>
// error: cannot inherit from sealed class: A1
sealed interface A1<T> permits B1<T> {}
class B1<T> implements A1<T> {}
// error: cannot inherit from sealed class: A2
sealed interface A2<T> permits B2 {}
class B2<T> implements A2<T> {}
// error: cannot inherit from sealed class: A3
sealed interface A3<T> permits B3 {}
class B3 implements A3 {}
>> 2.4) Question: Are instanceof checks planned in switch expressions?
>>
>> record A();
>>
>> var res = switch(new Object()) {
>> case A -> 1 // instanceof A check
>> default -> 0
>> };
>
> Yes, eventually, but its not clear whether the binding variable will be required:
>
> case A a -> 1
>
> or whether omitting the binding variable will be OK. I am worried about ambiguities in `identifier` as a pattern, since it could be a constant pattern or a type pattern.
>
I see, that makes sense. Scala uses `case _: A => …`.
I don’t know if it would be a good idea to use `_` in Java when the binding variable isn’t needed (currently it fails on patterns-deconstruction).
Having a proper name `case B b -> ...` is straight forward and also the case in lambda expressions for example `(A ignored, B b) -> ...`.
class Test {
public static void main(String[] args) {
var res = switch(new Object()) {
case B _ -> 1;
^--- error: : or -> expected
^-- error: '_' used as an identifier
default -> -1;
};
}
}
class B {}
More information about the amber-dev
mailing list