[threeten-dev] lambda + threeten
Brian Goetz
brian.goetz at oracle.com
Mon Dec 3 10:36:04 PST 2012
Yes, this was an extensively discussed point in the EG. It came down to
consistency in philosophy and user model.
The philosophy argument is: default methods are designed for evolving
interfaces. Yes, they can be used as a form of traits-lite, which is
fine as far as this goes (and it goes pretty far), so long as you don't
go all wishful-thinking on us and pretend they are full-blown traits.
The desire to let interface methods provide implementations for Object
methods is really a way of saying "but I want this to be traits." As
long as you think about it as "glass 98% full" rather than "glass 2%
empty", you're fine :)
The user-model argument is: we have dramatically reduced the pain
surrounding reasoning about multiple inheritance by adopting some very
simple rules, the foremost of which is "class methods always win." If
there is an implementation on the class hierarchy, we don't even look at
the interface hierarchy. Not only does this guarantee compatibility, it
is very simple to reason about. This means that anything inherited from
Object wins. We could have, of course, changed the rules, but that
would have made the feature more complicated to address a use case that
is already sliding down a slippery slope; attempts to define Object
methods in interfaces assumes that you are using those interfaces as if
they can only be singly inherited. The reality is that methods like
toString, equals, and hashCode are tightly bound to the object's state,
and the state lives in the class, not the interfaces. Unless we could
enforce that only one interface was managing the state, such a feature
would cause more trouble than it solves.
Default methods may reduce the need for abstract classes, but they don't
eliminate it. Fields are one reason we still need them; Object methods
are another.
Glad to hear the conversion was mostly painless!
On 12/3/2012 1:22 PM, Xueming Shen wrote:
>
> I experimented the lambda repo + threeten repo to see how much we
> might need to do when lambda stuff gets into the master. While it still
> took couple hours to (lots of emacs editing...) sort everything out, it
> appears it can be done smoothly in hours.
>
> The only issue (not straightforward/simply copy/paste) I found is that
> three j.l.Object methods equals/hashCode/toString can NOT be
> default-method-ed in ChronoLocalD/DT/ODT/ZDT. It appears to be not
> allowed. Sorry, if this is a well-known spec that I'm not aware of , I'm
> a lambda newbie:-) they need to be simply defined as @override
> method and the (default) impl need to go into their corresponding impl
> classes.
>
> I'm not sure if all those utility methods in "jdk8Methods" have been
> in jdk8, so I did not touch them this time. But at least so of them
> are there already. Should we just migrate?
>
> Here is the java doc for the combined threeten_lambda
>
> http://cr.openjdk.java.net/~sherman/jdk8_threeten/api_lambda/
>
> The webrev/diff for the changes, if interested.
>
> http://cr.openjdk.java.net/~sherman/jdk8_threeten/defaultM
>
> And yes, I have my first lambda + threeten test, and trying Stephen's
> fancy functional interfaces With/MinusAdjuster :-)
>
> I might write a blog for our first lambda+threeten repo/binary.
>
> -Sherman
>
> --------------------------------------------------------------------
> LocalDateTime now = LocalDateTime.now();
> Random r = new Random();
>
> DateTimeFormatter fmt =
> DateTimeFormatters.pattern("yyyy-MM-dd HH:mm:ss [EEEE]");
>
> int total = 100;
> int days = 2; // days to delay
> int minMon = 2;
> int maxMon = 6;
>
> Streams.repeatedly(total, () -> (now.withYear(2012)
>
> .withDayOfYear(r.nextInt(365) + 1)
> .with(SECOND_OF_DAY,
> r.nextInt(86400))))
> .sorted((d1, d2) -> d1.compareTo(d2))
> // .filter(d -> (d.getMonthValue() >= minMon &&
> d.getMonthValue() <= maxMon))
> .tee(d -> {System.out.printf(" %-30s ", fmt.print(d));})
> .map(d -> (d.with(dd -> (dd.with(EPOCH_DAY,
> dd.getLong(EPOCH_DAY) + days)))))
> .tee(d -> {System.out.printf(" --> %-30s ",
> fmt.print(d));})
> .map(d -> (d.minus(dd -> (dd.with(EPOCH_DAY,
> (dd.getLong(EPOCH_DAY)- days))))))
> .forEach(d -> {System.out.printf(" --> %-30s%n",
> fmt.print(d));});
>
More information about the threeten-dev
mailing list