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+cc...@openjdk.java.net> wrote:
> 
> On Mon, 9 Aug 2021 12:28:23 GMT, CC007 <github.com+5381337+cc...@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).
> 

Reply via email to