Final defenders
Aleksey Shipilev
aleksey.shipilev at oracle.com
Wed Aug 8 02:45:47 PDT 2012
David,
I would agree with you, if not the amusing part of that: it is not my
code (yet), but the code there in lambda/it2-bootstrap. If we can't help
ourselves from exploiting this, how could we morally justify everyone
else to stop using it?
"final defenders" patchwork seems to be lesser evil comparing to
full-blown traits, or requiring abstract SAM classes for lambdas, or
burying our heads in the sand, and pretending this is not the issue.
Otherwise, we should set the example of not using defenders as the
semi-traits, and keep with it. The sanest alternative I could think of
for StatefulOp is stop propagating metadata in getters, but instead
infer the metadata (i.e. isStateful) from the type alone (instanceof,
here I come).
-Aleksey.
On 08/08/2012 01:32 PM, David Holmes wrote:
> Aleksey,
>
> I think this just highlights that default methods are not intended to be
> what you are trying to make them. They exist to provide an
> implementation where none would otherwise exist, not to be an enforced
> and non-overridable implementation. They might look like traits from a
> certain angle but they are at best a very limited form.
>
> If Java needs traits (I said "if"!) then add traits, but don't try to
> contort interfaces into traits. A language will only stretch so far
> before it breaks.
>
> My 2c.
>
> David
>
> On 8/08/2012 12:34 AM, Aleksey Shipilev wrote:
>> Hi,
>>
>> TRAITS! Now, while Brian is gasping with exertion, I'll continue. While
>> studying the it2-bootstrap branch code, I have come across using
>> defenders in trait-like fashion:
>>
>> public interface StatefulOp<T, U, V> {
>> public boolean isStateful() default {
>> return true;
>> }
>> }
>>
>> In this case, the defender is not particularly the fallback default, but
>> really an enforced implementation. However, lacking language support for
>> these cases, I can do:
>>
>> public class MyRogueOp implements StatefulOp {
>> public boolean isStateful() {
>> return false; // eat that!
>> }
>> }
>>
>> ...and the defender rules will count my concrete implementation as
>> legitimate one. This makes relying on isStateful() quite a bad idea in
>> the library.
>>
>> That makes me thinking if we need to embrace it, and realize that some
>> of the defenders are really final. My suggestion is simple: let's mark
>> the final defenders "final"!
>>
>> In simplest form:
>>
>> public interface StatefulOp<T, U, V> {
>> public final boolean isStateful() default {
>> return true;
>> }
>> }
>>
>> "final" is not allowed in interfaces by the current rules, so we can use
>> this loophole to introduce a new meaning. However, this feels wrong to
>> provide the default implementation, and instantly forbid the extension.
>> So, maybe this is better:
>>
>> public interface StatefulOp<T, U, V> {
>> public boolean isStateful() final {
>> return true;
>> }
>> }
>>
>> This should be more complicated to implement in compiler, but it clearly
>> mandates the method body is the final implementation.
>>
>> This is not completely enforceable in the compile time, and so it
>> complicates the method dispatch a bit. We need to check if there is any
>> superclass final defender in the hierarchy, that can piggyback on the
>> defender selection we have now. Also, two colliding defenders, no matter
>> if the pairs are default/final, default/default, or final/final should
>> render the same error as default/default collision now.
>>
>> Additional concern is the evolution. We need to explore two things:
>> 1. Can we add "final" to the defender on the existing interface?
>> 2. Can we remove "final" from the defender on the existing interface?
>>
>> The answer to both seems to be "yes", because the same class of bugs we
>> have already with abstract classes and visibility rules, also
>> unenforceable with separate compilation. We can still do compile-time
>> checks so that code compiled at once would never throw a linkage error.
>>
>> Thoughts?
>>
>> -Aleksey.
>>
More information about the lambda-dev
mailing list