JEP proposal: Improved variance for generic classes and interfaces
elias vasylenko
eliasvasylenko at gmail.com
Tue Oct 28 01:21:46 UTC 2014
Am I correct that to just have the bridge method call the 'overriding'
method would give the following behaviour?:
Bar bar;
Integer i;
// ...
bar.test(i); // false
((Foo) bar).test(i); // false
((Predicate) bar).test(i); // true
I can see why this is undesirable, but fwiw I'd be okay with it...
On 28 Oct 2014 00:19, "elias vasylenko" <eliasvasylenko at gmail.com> wrote:
> Ah, good point. Covariance is still easy to have without any such fuss, so
> far as I can see, but having the one without the other is no good.
>
> I still think this at least bears further consideration. There could still
> be a solution in allowing contravariant overriding in this particular
> instance, i.e. having the user only need to implement test(Number) and
> having the bridge method just call that... since conceptually test(Integer)
> *should* have effectively been a bridge method *itself* to test(Number)
> anyway. If anything, it would be better this way regardless of the erasure
> issue imo, since it's just more strongly enforcing contravariance
> relationship encoded by the Predicate<? super T> syntax.
>
> There are still problems, since of course suddenly allowing contravariant
> overrides in one specific scenario creates situations which behave
> inconsistently with people's current expectations e.g.:
>
> class Foo implements Predicate<Integer> {
> public boolean test(Integer value) {return false;}
> }
>
> class Bar extends Foo implements Predicate<Number> {
> public boolean test(Number value) {return true;}
> }
>
> foo.test((Integer) i); // returns true instead of false when invoked
> on an instance of Foo!
>
> Now that we have default methods we couldn't even just limit the feature
> to interfaces to avoid the problem.
>
> The only remotely tenable solution would be to force users to explicitly
> override test(Integer) with a method which does nothing but forward the
> invocation to test(Number). This would solve the erasure/bridge ambiguity,
> as well as the general ban on contravariant overrides, but still isn't
> ideal just because it feels a bit clunky... Syntax to explicitly mark a
> method as a 'forwarding' method without having to specify a body would
> help, but that is clearly outside the scope of this proposal, and a no-go
> unless it could be justified in and of itself as worth the added language
> complexity...
>
> Any thoughts? Have I talked myself out of this? Are there other problems
> I've missed in rambling on which make this moot, or does that about cover
> it?
>
> Cheers,
>
> Eli
>
> On 27 October 2014 23:03, Remi Forax <forax at univ-mlv.fr> wrote:
>
>>
>> On 10/27/2014 11:52 PM, Dan Smith wrote:
>>
>>> On Oct 26, 2014, at 4:53 PM, elias vasylenko <eliasvasylenko at gmail.com>
>>>> wrote:
>>>>
>>>> Just a quick question/suggestion: it seems like a handy side-effect of
>>>> the proposed changes is the potential for relaxation of the limitation on
>>>> reimplementation of interfaces with different generic parametrisations, and
>>>> I'm wondering if you've considered this.
>>>>
>>>> For example, it should be possible to allow something like this:
>>>>
>>>> class Foo implements Predicate<Integer> {}
>>>>
>>>> class Bar extends Foo implements Predicate<Number> {}
>>>>
>>>> Since declaration-site variance guarantees compatibility of the
>>>> overriding parametrisation. Of course we can't technically override
>>>> test(Integer) with test(Number)... but from an outsiders perspective I
>>>> don't see this as incompatible with current language design philosophy...
>>>> At any rate, covariance should be more straightforward
>>>>
>>>> I'm sure this would have come up if it hasn't already, but I couldn't
>>>> find any explicit mention of it.
>>>>
>>> That's a good idea, and not something we've looked into yet. Thanks for
>>> the suggestion.
>>>
>>> —Dan
>>>
>>
>> The problem here is not a typing problem but an erasure problem, both
>> Predicate<Integer> and Predicate<Number> require to generate a bridge
>> method but both test(Integer) and test(Number) have the same erasure
>> test(Object). So it's not possible without full reification to implement
>> that bridge.
>>
>> cheers,
>> Rémi
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20141028/e89233f6/attachment.html>
More information about the compiler-dev
mailing list