Могу ли я переопределить закрытый метод родительского класса с помощью Byte Buddy?

Основываясь на идее Могу ли я переопределить частные методы с помощью Byte Buddy?, я хотел бы переопределить закрытый метод из родительского класса. Это возможно? Или это как проблема курицы и яйца?

Спасибо!


person Jordi Llach    schedule 17.02.2017    source источник
comment
Не понятно, что вы спрашиваете. Метод private имеет отношение только к своему объявленному классу, который является классом, который вы должны переопределить. Является ли этот класс суперклассом другого класса, не имеет значения.   -  person Holger    schedule 17.02.2017
comment
Поскольку частный метод A, в свою очередь, вызывает другие защищенные и частные методы пакета, которые я не хочу заменять или копировать, мне нужно переопределить частный метод A в B (подкласс)   -  person Jordi Llach    schedule 17.02.2017
comment
В B такого метода нет. Метод private для A существует только в A. Единственная возможность решить вашу задачу — заменить метод private A на метод, который выполняет проверку this instanceof B и делегирует старый код, если проверка оценивается как false. Я не знаю, поддерживает ли ByteBuddy такой инструментарий, но в любом случае это выглядит сомнительным дизайном.   -  person Holger    schedule 17.02.2017
comment
Имеет ли этот вопрос смысл или нет, ByteBuddy завершается с ошибкой java.lang.UnsupportedOperationException: сбой переопределения класса: попытка изменить схему (добавить/удалить поля)   -  person Jordi Llach    schedule 17.02.2017
comment
Возможно, это поможет показать, что вы пробовали…   -  person Holger    schedule 17.02.2017


Ответы (1)


Частные методы не отправляются виртуально, поэтому вы не можете изменить отправку частного метода внутри подкласса. Единственный способ сделать это — напрямую жестко закодировать условную отправку в частный метод.

Вы можете сделать это, используя класс Advice Byte Buddy в сочетании с агентом Java. Агент Java будет выглядеть следующим образом:

new AgentBuilder.Default()
  .disableClassFormatChanges()
  .with(RedefinitionStrategy.REDEFINITION)
  .type(is(ClassWithPrivateMethod.class))
  .transform((builder, type, cl, module) -> {
     return builder.visitor(Advice.to(MyAdvice.class)
                                  .on(named("privateMethod")));
   }).install(inst);

где код MyAdvice встроен в начало метода с именем privateMethod. Условная отправка будет выглядеть следующим образом:

class Adv {
  @OnMethodEnter(skipOn = OnNonDefaultValue.class)
  static boolean intercept(@This ClassWithPrivateMethod self) {
    if (self instanceof ParentClass) {
      // Your code
      return true;
    } else {
      return false;
    }
  }
}

Возвращая true и используя условие пропуска, вы выполняете фактический код только в том случае, если возвращается false.

person Rafael Winterhalter    schedule 18.02.2017