RFR: 8272137: Make Collection and Optional classes streamable [plug for Extensible interface]
Alan Snyder
javalists at cbfiddle.com
Tue Aug 17 18:55:23 UTC 2021
This provides an opportunity for me to promote what I believe is a much more important missing interface, namely, an interface that supports a semantic replacement for type casting.
Using type casting (instanceof) is a really bad way to test an object for an optional capability.
The reason is that instanceof is strictly limited by how the object is implemented. It will only work if the object *directly* implements the interface. It does not support an object that might provide the requested interface using an auxiliary object. It doesn’t support delegation at all. If you try to wrap an object with a transparent wrapper implemented using delegation, the wrapper must support exactly the interfaces that you expect from the wrapped object. If some of those are optional, you wind up with many versions of the wrapper to ensure that instanceof will work on the wrapper as expected.
This is hardly a new idea. I’ve seen this idea in several major libraries. But, because Java does define its own version of this interface, this approach cannot be used in general.
I suspect it would be useful for some of the problems being discussed here.
For concreteness, this is how I define it:
public interface Extensible
{
<T> @Nullable T getExtension(@NotNull Class<T> c);
}
with a static method used in place of instanceof:
public static <T> @Nullable T getExtension(@Nullable Object o, @NotNull Class<T> c)
{
if (o == null) {
return null;
}
if (c.isInstance(o)) {
return c.cast(o);
}
if (o instanceof Extensible) {
Extensible x = (Extensible) o;
return x.getExtension(c);
}
return null;
}
> On Aug 17, 2021, at 10:54 AM, CC007 <github.com+5381337+cc007 at openjdk.java.net> wrote:
>
> On Mon, 9 Aug 2021 12:28:23 GMT, CC007 <github.com+5381337+CC007 at openjdk.org> wrote:
>
>> create Streamable and ParallelStreamable interface and use them in Collection and Optional
>
> Ah ok, I see your point. In the case that you want to have something be only `Streamable`, you can create an interface like this (fixed missing method type param and added `ofCollection`:
>
> public interface Streamable<T> {
>
> Stream<T> stream();
>
> static <T> Streamable<T> ofIterable(Iterable<T> iterable) {
> return () -> StreamSupport.stream(iterable.spliterator(), false);
> }
>
> static <T> Streamable<T> ofCollection(Collection<T> collection) {
> return collection::stream;
> }
> }
>
> This will indeed allow you to only expose the `stream()` method, even to the degree that you can't even expose the other methods with type casting, which is a nice side effect. You could also add a static method for `ofOptional`, if required, but you made a good point about `Optional.stream`'s general use case (though it could still be used as a stream when needed).
>
More information about the core-libs-dev
mailing list