Question about records and overriding their "magic methods"
David Alayachew
davidalayachew at gmail.com
Thu Sep 21 18:40:05 UTC 2023
Hello Rémi,
Thank you for your response!
> If you really really want to do it, you can use the
> bootstrap method in java.lang.runtime.ObjectsMethods but
> it's ugly.
That's actually way better than I thought it would be. It's surprisingly
direct too.
> We also do not want to close the door to supporting
> super.x() if at some point in the future if the VM spec
> is changed to introduce a way to generate bridge methods
> at runtime.
>
> The record methods toString/equals/hashCode will be
> declare as abstract bridge method in that case.
I brushed up on bridge methods for this response -
https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html
I get the concept, but I am curious what having that at runtime would give
us that we don't already get at compile time. I don't quite see it.
Thank you for your time and help!
David Alayachew
On Thu, Sep 21, 2023 at 1:49 PM Remi Forax <forax at univ-mlv.fr> wrote:
>
>
> ------------------------------
>
> *From: *"Brian Goetz" <brian.goetz at oracle.com>
> *To: *"David Alayachew" <davidalayachew at gmail.com>, "amber-dev" <
> amber-dev at openjdk.org>
> *Sent: *Thursday, September 21, 2023 7:18:13 PM
> *Subject: *Re: Question about records and overriding their "magic methods"
>
> We explored this topic somewhat when designing the feature.
>
> When you override a method x, you can still delegate (via super.x()) to
> the thing you override. We considered doing the same here (delegating to
> default.x()), but concluded that this failed the power-to-weight-ratio
> test, because usually you do not want to _refine_ an
> equals/toString/hashCode calculation, but instead broaden it (such as
> comparing arrays by contents rather than by ==.)
>
> If you pull on this "string" a bit, the API that you would want here is
> complex and enormous, and has as many tuning knobs as a Lombok. So
> refactoring records that customize Object methods becomes a
> higher-responsibility activity. Leave "future you" some comments for what
> you were thinking today.
>
>
>
> If you really really want to do it, you can use the bootstrap method in
> java.lang.runtime.ObjectsMethods but it's ugly.
>
> public class CallingRecordToStringDemo {
>
> record Foo(String blah, int value) {
> private static final MethodHandle TO_STRING;
> static {
> var lookup = MethodHandles.lookup();
> var components = Foo.class.getRecordComponents();
> CallSite callsite;
> try {
> callsite = (CallSite) ObjectMethods.bootstrap(lookup,
> "toString",
> MethodType.methodType(String.class, Foo.class),
> Foo.class,
> Arrays.stream(components).map(RecordComponent::getName).collect(Collectors.joining(";")),
> Arrays.stream(components).map(c -> {
> try {
> return lookup.unreflect(c.getAccessor());
> } catch (IllegalAccessException e) {
> throw new AssertionError(e);
> }
> }).toArray(MethodHandle[]::new));
> } catch (Throwable e) {
> throw new AssertionError(e);
> }
> TO_STRING = callsite.dynamicInvoker();
> }
>
> @Override
> public String toString() {
> try {
> return (String) TO_STRING.invokeExact(this);
> } catch (Error e) {
> throw e;
> } catch (Throwable e) {
> throw new AssertionError(e);
> }
> }
> }
>
> public static void main(String[] args) {
> System.out.println(new Foo("blah", 42));
> }
> }
>
>
> We also do not want to close the door to supporting super.x() if at some
> point in the future if the VM spec is changed to introduce a way to
> generate bridge methods at runtime.
> The record methods toString/equals/hashCode will be declare as abstract
> bridge method in that case.
>
> regards,
> Rémi
>
>
>
>
> On 9/21/2023 1:00 PM, David Alayachew wrote:
>
> Hello Amber Dev Team,
>
> Let's say I have a record like the following.
>
> record ComplexRecord(int blah /* and many more components */) {}
>
> Next, let's say that I want to override my toString, to include some
> derived information.
>
> Obviously, putting the derived info into the toString is easy, but how do
> I go about INCLUDING it with my original implementation of toString that
> was magically created for me by Java?
>
> If I try to fully recreate my toString, I run the risk of it becoming
> out-of-date upon refactor. Best I can come up with is nesting another
> record with the toString overloaded. Also not ideal.
>
> Thank you for your time!
> David Alayachew
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230921/6076feb3/attachment-0001.htm>
More information about the amber-dev
mailing list