Search code examples
javajava-recordjava-15

Java 15 - records with different return type for getter


Is it possible to implement something like this in java 15?

record Something(
        SomeId id,
        MyProp myProp,
        MaybeProp maybeProp
){
    public Something(SomeId id, MyProp myProp){
        this(id, myProp, null);
    }

    public Optional<MaybeProp> maybeProp(){ //problematic line
        return Optional.ofNullable(maybeProp);
    }
}

Here I get the exception

(return type of accessor method maybeProp() must match the type of record component maybeProp)

So - I understand what the problem is; But is there then some other solution for this? How to have optional member inside record, that I do not need to initialize using Optional.of()?


Solution

  • You can't hide or change the return type of the automatically generated read accessor for a record's field.

    One way to achieve what you are looking for is to have the record implement an interface and then use that instead of the record type:

    interface PossibleSomething {
        Optional<Something> maybeSomething();
    }
    
    record SomethingRecord(Something something) implements PossibleSomething {
        public Optional<Something> maybeSomething() {
            return Optional.ofNullable(something);
        }
    }
    
    // user code:
    PossibleSomething mySomething = new SomethingRecord(something);
    mySomething.maybeSomething().ifPresent(...)
    

    By using PossibleSomething in the calling code you are explicitly declaring that you don't need direct access to the field but will access it only through the interface's accessor.

    As a matter of design philosophy, records are explicitly intended (according to the JEP) to support modelling data as data. In other words their use case is when you have straight immutable data you want to store and give the user direct access to. That is why they don't support changing the accessors: it's not what records are for. The pattern I show above (i.e. a record implementing an interface to hide access) is a way to hide the use of a record as an implementation detail and control access to the fields.