I'm trying out the new records feature with java 14, currently in preview.
I know that in Java one has to have exactly one public class per file but with the new record syntax being so nice and short it just seem wasteful to have a bunch of files each with a single line of code in them.
In particular I wanted to try to model a simple AST like this, and I think that having everything together in one file really improves readability and comprehension.
package com.company;
public interface Expression {
}
public record IntExp(int value) implements Expression {
}
public record AddExp(Expression left, Expression right) implements Expression {
}
public record SubtractExp(Expression left, Expression right) implements Expression {
}
// Etc..
But unfortunately this will not compile.
So my question is:
Is there any way around this limitation or some way to keep code like this all in one place?
Inner classes, along with sealed types seem to be what you're after. Java 15 has introduced sealed types as a preview feature.
You've stated that you wanted to model an AST in one single file. An AST is exhaustive. And this exhaustiveness can be modeled with inner classes and sealed types.
In your particular example, if you define the super type along with all its permitted subtypes in the same compilation unit (with the subtypes being inner classes), the compiler will automatically infer the
permits
for you:Here, the compiler will automatically infer
IntExp
,AddExp
andSubtractExp
aspermits
and won't allow any other types (declared in any other compilation unit) to neither extend nor implement theExpression
interface.