Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"this" on static extension methods #348

Closed
joseaio opened this issue Mar 30, 2022 · 3 comments
Closed

"this" on static extension methods #348

joseaio opened this issue Mar 30, 2022 · 3 comments

Comments

@joseaio
Copy link

joseaio commented Mar 30, 2022

Already known that static method in Java don't have a "this" context. But this is not true with other OO languages ("this" on class method referenced the called Class).

I like a static logging method warn() declared on Object, for use on any class

If "static extension methods" allows an optional (for retrocompatibility) first parameter with the called class, as this one:

package <your-project>.extensions.java.lang.Object;

@Extension
public class MyObject {

  private static final String jdk_logger_packages = "jdk.logger.packages";
  protected static final Map<Class, Logger> logs = new HashMap<>();

  static {
    // Ignore logger wrappers, as this, when writes class and method on log traces
    System.setProperty(jdk_logger_packages, MyObject.class.getPackageName());
  }

  private static Logger log(Class clazz) {
    if (!logs.containsKey(clazz)) {
      logs.put(clazz, Logger.getLogger(clazz.getName()));
    }
    return logs.get(clazz);
  }

  @Extension
  protected static void warn(@This Class clazz, String msg) {
    log(clazz).warning(msg);
  }

Now, I can write logs, on any class, calling to static method: warn("message")

note: this solution centralize logging framework dependency on single class (I don't like imports of logging framework on all classes)

@joseaio joseaio changed the title "this" on static method "this" on static extension methods Mar 30, 2022
@joseaio
Copy link
Author

joseaio commented Apr 1, 2022

This is not a solution (I prefer "this" on class/static methods), but a possible workaround (I don't known if cause a poor performance):

Please note the use of StackWalker on warn() method to determine the caller.

package <your-project>.extensions.java.lang.Object;

@Extension
public class MyObject {

  // Create walker constant to reduce initialization time
  private static final StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);

  private static final String jdk_logger_packages = "jdk.logger.packages";
  protected static final Map<Class, Logger> logs = new HashMap<>();

  static {
    // Ignore logger wrappers, as this, when writes class and method on log traces
    System.setProperty(jdk_logger_packages, MyObject.class.getPackageName());
  }

  private static Logger log(Class<?> clazz) {
    if (!logs.containsKey(clazz)) {
      logs.put(clazz, Logger.getLogger(clazz.getName()));
    }
    return logs.get(clazz);
  }

  @Extension
  public static void warn(String msg) {
    // Use walker to determine the caller class, to get its Logger
    log(walker.getCallerClass()).warning(msg);
  }
}

I changed warn() method to public because protected extension methods causes error on Manifold (see issue 349) FIXED on Manifold version >= 2022.1.8

@rsmckinney
Copy link
Member

See "Smart" static methods with @ThisClass. Paired with @Self I think you can accomplish what you are looking for with static methods here.

@joseaio
Copy link
Author

joseaio commented Apr 24, 2022

Great example and another use case: generic factory with static method (on superclass or interface). In the past, I also needed this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants