Skip to content

Replace Optional<X> with Optional<? extends X> #369

@ST-DDT

Description

@ST-DDT

I encountered a little problem while looking at the Sponge Implementation and extending existing events.

The issue
I can overwrite every method to return a more precise result than the base interface specifies. However using the Optional destroys that benefit if used the way we currerntly do.

Here is an example code

public interface Test {

    Optional<Test> getSelf();

    Optional<? extends Test> getBetterSelf();

}

and the second file

public class Proof implements Test {

    @Override
    // public Optional<Proof> getSelf() { - NOT POSSIBLE
    public Optional<Test> getSelf() {
        // return Optional.of(this); - NOT POSSIBLE
        return Optional.of((Test) this);
    }

    @Override
    public Optional<? extends Proof> getBetterSelf() {
        return Optional.of(this);
    }

    public void foo() {
        Proof self = getBetterSelf().get();
        // Proof self2 = test.getSelf().get(); - NOT POSSIBLE
        Proof self2 = (Proof) test.getSelf().get();
    }

}

Image the Sponge server itself has a specific subclass for one of its events, which uses a subclass of the original class/interface because a method was added that is required for further use. So if you listen to the given event and you try to get it, you will actually get the base interface because you have to downcast it, but if you use the <? extends T> for example this is no longer an issue you class can simply overwrite the return type and everything will be fine.

If we change it we have basically three benefits:

  • Avoid unnecessary casting while creating the Optional
  • Avoid unnecessary casting while getting the Optional's value
  • Allow other APIs to extend our API more safely and freely.

I suggest replacing/changing it in the entire API (where the Optional references a class within the org.spongepowered.api.** package) , i also offer my help to change it.
This would also include immutable Iterables, Collections, ...., Maps.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions