Multiple SAMs for same concept

Collin Fagan collin.fagan at gmail.com
Thu Jul 15 17:11:41 PDT 2010


*> just because the signatures are identical doesn't mean the contracts are
identical*

This is true for any interface. Look at the implementations of Map. They are
all different enough that many times they are not interchangeable. Yet Map
appears in signatures of methods and constructors and everyone just hopes
that they get something compatible. Most of the time the differences don't
show themselves and that's good enough. I think in this case it's also good
enough.

I think the biggest obstacle here, as others have pointed out, is object
identity. If this was implimented using a MethodHandle and not a wrapper
class could one work around identity?

Collin

On Thu, Jul 15, 2010 at 7:00 PM, Lawrence Kesteloot <lk at teamten.com> wrote:

> In addition, just because the signatures are identical doesn't mean
> the contracts are identical. Provider.get(), for example, must never
> return null, but who knows what Generator.op() might return? Same with
> unchecked exceptions, allowed values of parameters, etc. The
> programmer should be forced to explicitly convert from one to the
> other (as in your "less than ideal" examples) to show that he has
> consciously decided to treat the SAMs as compatible.
>
> Lawrence
>
>
> On Thu, Jul 15, 2010 at 4:49 PM, Pavel Minaev <int19h at gmail.com> wrote:
> > On Thu, Jul 15, 2010 at 4:34 PM, Stephen Colebourne
> > <scolebourne at joda.org> wrote:
> >> One problem noted with the removal of function types is that multiple
> >> SAMs with the same signature are not compatible. For example:
> >>
> >>
> http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/extra166y/Ops.Generator.html
> >>
> http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/Supplier.html
> >>
> http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/Provider.html
> >>
> >> Having these different incompatible definitions is problematic, for
> >> example when the developer has created a library of reusable
> >> implementations implementing one SAM, and then wants to use them using
> >> another (eg. a newly added JDK SAM).
> >>
> >> Given the method:
> >>  private void process(Generator<String> gen) { ... }
> >>
> >> the most recent draft SotL would allow the following two choices for
> conversion:
> >>  Supplier<String> supplier = ...
> >>  process( {-> supplier.supply()} );  // manual conversion to a Generator
> >>  process( supplier#supply() );  // using method ref to manually
> >> convert to Generator
> >>
> >> While the two solutions are not terrible, they are less than ideal. I
> >> would argue that the ideal would be:
> >>  process(supplier);  // auto-boxed from Supplier to Generator
> >
> > Such "autoboxing" (since no boxing happens here, I'd rather call it
> > "autowrapping") wouldn't preserve object identity. I think it would be
> > very confusing to pass a reference to object, only to receive a
> > reference to a completely different (as in, r1 != r2) object on the
> > other side - especially without any explicit casts or other indication
> > that something unusual is going on.
> >
> > This wasn't a problem with primitives because they don't have their
> > own object identity
> >
> >> One compromise option I came up with was:
> >> process( supplier# );
> >
> > This looks more reasonable.
> >
> >
>
>


More information about the lambda-dev mailing list