Java Reflect / AOP переопределяет приватный метод супертипа - PullRequest
2 голосов
/ 14 декабря 2010

Можно ли вообще "переопределить" закрытый метод суперкласса в Java?

Класс, метод которого я хочу переопределить, является сторонним классом, поэтому я не могу изменить источник.Было бы идеально, если бы был какой-то способ рефлексивно установить метод для класса.

В качестве альтернативы, если возможно перехватить закрытый метод стороннего класса, тогда это подойдет.

Ответы [ 4 ]

4 голосов
/ 17 октября 2012

YES .Вы можете сделать это с аспектом.Это не истинное переопределение, но результат будет таким.

Здесь ваш суперкласс;

public class MySuperClass {

    private void content(String text) {
       System.out.print("I'm super " + text);
    }

    public void echo() {
       content("!");
    }        
}

Создайте интерфейс, который содержит подобный метод;

public interface Content {
    void safeContent(String text);
}

Createаспект, который заставляет суперкласс реализовать этот интерфейс и добавить советник по вызову для его вызова.

public privileged aspect SuperClassAspect {

    void around(MySuperClass obj)
            : execution(* content(String)) && target(obj) {

        Object[] args = thisJoinPoint.getArgs();
        ((Content) obj).safeContent((String) args[0]);
    }

    // compiler requires
    public void MySuperClass.safeContent(String text) {}


    declare parents :MySuperClass implements Content;
}

Создайте свой дочерний класс, который расширяет super и реализует этот интерфейс.

public class Overrider extends MySuperClass implements Content {

    public void safeContent(String text) {
        System.out.print("Not that super " + text);
    }
}

Теперь, если вы создадите объект Overrider и вызовете метод echo, у вас будет выходной метод метода OverConders safeContent.

3 голосов
/ 14 декабря 2010

У вас нет законного способа сделать это.Но я могу предложить вам следующие решения.

  1. Вы действительно хотите переопределить этот метод?Попробуйте подумать о другом решении.
  2. Java проверяет права доступа только во время компиляции.Вы удивлены?Я был очень удивлен, узнав этот факт.Таким образом, вы можете создать каркас стороннего класса (даже с пустыми реализациями.).Интересный метод должен быть protected вместо private.Теперь напишите свой подкласс и скомпилируйте его с вашей заглушкой.Затем упакуйте только ваш подкласс и попробуйте запустить его с «настоящим» классом.Он должен работать.Я не пробовал этот трюк с наследованием, но я пробовал его, когда мне нужно было получить доступ к приватному методу или полю, и он работал нормально для меня.
  3. Попробуйте использовать динамический прокси, который оборачивает ваш класс и меняет его реализацию.Я не знаю, что именно вы делаете, поэтому я не уверен, что вы действительно можете использовать этот метод.Но я надеюсь, что вы можете.Если нет, вернитесь к # 1 или # 2.
2 голосов
/ 14 декабря 2010

Можно ли вообще "переопределить" закрытый метод суперкласса в Java?

Нет

Я не думаю, что с помощью Reflection будет твик, он сломается OOP там

0 голосов
/ 17 ноября 2014

да, это возможно, но вы не должны этого делать, потому что это противоречит одному из принципов SOLID . Точнее это противоречит принципу подстановки Лискова .

Примечание: Пусть q (x) свойство, доказуемое для объектов x типа T. Тогда q (y) должно быть доказуемо для объектов y типа S, где S является подтипом T.

Другими словами, закрытый метод является свойством объекта, поэтому ваш объект наследуемого типа должен иметь то же свойство. То же самое с бросками для методов.

Java ограничивает это из-за этого.

...