未知方法调用的运行时委派

时间:2015-03-21 02:03:38

标签: java methods delegates anonymous

背景

考虑对象 Alice Bob Eve 。在Smalltalk中,Alice可以向Bob发送消息,然后Bob委托给Eve,而Bob不知道要委派的方法的名称(请参阅unknown method call的Smalltalk委派)。

问题

通过编写Alice代码,Java可以部分地emulate Smalltalk's behaviour

public void methodName() {
  Object bob = new Bob();

  try {
    ((BobInterface)bob).methodName();
  }
  catch( ClassCastException e ) {
    ((BobInterface)bob).doesNotUnderstand( new Method( name ) );
  }
}

这捕获了意图,但是冗长和重复(每种方法编码一次)。即使生成代码,它也是不切实际的。

Java 8引入了lambda表达式(请参阅此SO answer)。

问题

你怎么能把Bob编成胡言乱语,以致Bob没有实现的所有方法调用都是通过Bob从Alice传递给Eve?

例如,以下内容的变体应显示Received Alice's message!

public class Alice {
  public static void main( String args[] ) {
    Bob bob = new Bob();

    // Problematic line...
    bob.listen();
  }
}

public class Bob {
  private Eve eve;

  // When "bob.listen()" is called, this should be invoked...
  public void doesNotUnderstand( Method m ) {
    delegate( eve, m );
  }
}

public class Eve {
  public void listen() {
    System.out.println( "Received Alice's message!" );
  }
}

问题约束

  • 欢迎使用Lambda表达式,反射或两者。
  • 第三方库(例如字节码操作)和方面并不理想。
  • Bob无法实现多个方法,也无法继承任何方法。
  • Alice和Bob都不应该包含重复的代码。

可以通过实现本地类来检索方法名称:

public class T {
   public static void main( String args[] ){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
      System.out.printf( "%s%n", name );
   }
}

相关

1 个答案:

答案 0 :(得分:0)

我不认为这样的事情在运行时是可能的。对于要编译的代码,您至少需要一个能够理解"所有方法。当然,您可以使用反射并动态调用所有内容,但是会丢失所有类型的安全性。我能看到这个工作的唯一方法是使用某种(预编译)代码生成(如果你不想依赖第三方库,你甚至可以使用标准的java注释)。