wildcatsの日記

赤羽在住でIT関係の会社の社長やってます。

JavaでMixin

mixiの日記で以前に同じようなことを書いたんだけど
http://d.hatena.ne.jp/brazil/20051001/1128099513
http://d.hatena.ne.jp/winebarrel/20051001#p6
を読んで自分がcglibで試したことをこっちにも書いてみることにする。
もしこれができれば実装の継承を
ある程度動的に組み込めるようになると思うんだけど
誰か良い手を知りませんか?


public interface Car {
  public void run();
}

public interface Seat {
  public void addSeat(Passenger pas);
}

public interface Bus extends Car, Seat {
}

public class BusSeatImpl implements Seat {

  private List list = new LinkedList();

  public void addSeat(Passenger passenger) {
    if (list.size() > 40) {
      throw new RuntimeException("定員オーバーです");
    }
    list.add(passenger);
  }
}


public class CarImpl implements Car {
  public void run() {
    System.out.println("Boo Boo!");
  }
}

public class Passenger {
  private String name;
}

public final class BusFactory {
  public static Bus create() {
    return (Bus) MixinFactory.create(Bus.class, new Object[] {new CarImpl(), new BusSeatImpl() });
  }
}

public final class MixinFactory {

  public static Object create(Class returnIface, Object[] mixObjects) {
    Object obj = Mixin.create(mixObjects);
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(obj.getClass());
    enhancer.setInterfaces(new Class[] { returnIface });
    enhancer.setCallback(new MethodInterceptor() {
      public Object intercept(Object obj, Method arg1, Object[] args,MethodProxy proxy) throws Throwable {
        return proxy.invokeSuper(obj, args);
      }
    });
    return enhancer.create();
  }
}


public void testCreate() {
  Bus bus = BusFactory.create();
  bus.addSeat(new Passenger());
  bus.run();
}
・・・

java.lang.NullPointerException
at com.wikihouse.wildcats0201.test.cglib.Seat$$MixinByCGLIB$$99ebebff.addSeat()
at com.wikihouse.wildcats0201.test.cglib.Seat$$MixinByCGLIB$$99ebebff$$EnhancerByCGLIB$$5ae6db92.CGLIB$addSeat$0()
at com.wikihouse.wildcats0201.test.cglib.Seat$$MixinByCGLIB$$99ebebff$$EnhancerByCGLIB$$5ae6db92$$FastClassByCGLIB$$c1ed6462.invoke()
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:167)
素直にjavassistとか使ってmixinするフレームワークを作った方が良いかな?