manifold-systems / manifold

Manifold is a Java compiler plugin, its features include Metaprogramming, Properties, Extension Methods, Operator Overloading, Templates, a Preprocessor, and more.
http://manifold.systems/
Apache License 2.0
2.37k stars 124 forks source link

Share fields and methods from other class #616

Open abccbaandy opened 1 month ago

abccbaandy commented 1 month ago

I want to do something like this https://stackoverflow.com/questions/56041893/java-how-to-share-field-and-method-between-classes

And those Delegate pattern is not work well, because the class is used by many framework/lib (ex: Spring data, jackson) So, I need a pure pojo in the runtime instead some magic method.

Describe the solution you'd like I think have an annotation @Extends, so I can do something like this.

@Extends(parent1.class)
@Extends(parent2.class)
public class Domain {
rsmckinney commented 1 month ago

Hi @abccbaandy. I read your stackoverflow link. If I understand correctly, essentially you would like to merge all the fields and get/set methods from one class into another. Manifold does not provide a feature for that, however there are workarounds involving manifold extension classes that may work for you.

For instance, you could use @Extension to add get/set methods. Since you can't add fields, you can store state in a thread-safe static map.

Something like this:

package extensions.org.example.Domain1;

import org.example.Domain1;
. . .

@Extension
public class MyDomain1Extension {
   private static final ThreadLocal<Map<String, Map<String, Object>>> _state = ThreadLocal.withInitial(WeakHashMap::new);

  public static Foo getFoo(@This Domain1 thiz) {
    return (Foo)getState(thiz, "Foo");
  }
  public static void setFoo(@This Domain1 thiz, Foo value) {
    setState(thiz, "Foo", value);
  }

  // more get/set methods
  // . . .

  // thread-safe state access

  private static Object getState(Domain1 thiz, String propertyName) {
     return _state.get().computeIfAbsent(thiz, __-> new HashMap<>()).get(propertyName);
  }

  private static void setState(Domain1 thiz, String propertyName, Object value) {
     _state.get().computeIfAbsent(thiz, __-> new HashMap<>()).put(propertyName, value);
  }
}

Another idea would involve modifying the JSON schema to include the additional state you need, if that suits your needs.