Вопрос

Я работаю со сторонней платформой, и оказалось, что мне нужно обернуть некоторые ее объекты в качестве делегата одного из моих классов.

class Foo { // 3rd party class.
    protected void method() {}
}

class FooWrapper extends Foo {
    private Foo mDelegate;

    public FooWrapper(Foo inDelegate) {
        mDelegate = inDelegate;
    }

    protected void method() {
        mDelegate.method(); // error can't access protected method() of mDelegate
    }
}

Итак, есть проблема.Мне нужно делегировать этот метод внутреннему объекту, но он защищен и, следовательно, недоступен.

Есть идеи о способах решения этой конкретной проблемы?Это для Java 1.3.

Это было полезно?

Решение

Почему вы создаете отдельный экземпляр Foo?FooWrapper уже является Foo.

class Foo {
    protected void method() {}
}

class FooWrapper extends Foo {

    protected void method() {
        super.method();
    }
}

Редактировать:если вам действительно нужен отдельный экземпляр, один из способов (хотя и немного некрасивый) — использовать отражение:

public class Foo {

    protected void method() {
        System.out.println("In Foo.method()");
    }
}

public class FooWrapper extends Foo {

    private Foo foo;

    public FooWrapper(Foo foo) {
        this.foo = foo;
    }

    public void method() {
        try {
            Method m = foo.getClass().getDeclaredMethod("method", null);
            m.setAccessible(true);
            m.invoke(foo, null);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Редактировать2: Основываясь на вашем комментарии ниже, создайте два подкласса Foo: один, который просто предоставляет общедоступные версии защищенных методов, и другой, который переопределяет все важные методы.Первый будет выглядеть и действовать точно так же, как Foo, второй может делать все, что вам нужно:

public class Foo {

    protected void method() {
        System.out.println("In Foo.method()");
    }
}

public class DelegateFoo extends Foo {

    public void method() {
        super.method();
    }
}

public class FooWrapper extends Foo {

    private DelegateFoo foo;

    public FooWrapper(DelegateFoo foo) {
        this.foo = foo;
    }

    public void method() {
        foo.method();
        /* extra logic here */
    }
}

Другие советы

Когда я оказался в такой ситуации, и это неприятно, но работает, это создать PublicFoo в том же пакете, что и Foo (но в вашем исходном коде), расширить Foo и переопределить protected метод и сделать его общедоступным.

Теперь FooWrapper может расширять PublicFoo и делать все, что вы захотите.

Однако обратите внимание: если исходный jar-файл подписан и запечатан, вам потребуется удалить подписи, прежде чем вы сможете его развернуть.(Вы можете зайти в каталог Manifest в банке и просто удалить сертификаты)

Что ж, если у него есть публичный доступ к его свойствам (будь то геттеры или общедоступные переменные), вы можете создать конструктор копирования:

public FooWrapper(Foo inDelegate) {
    this.property1 = inDelegate.getProperty1();
    this.property2 = inDelegate.getProperty2();
    // for every property
}

Если свойства являются объектами...отлично, даже лучше, потому что тогда любые внесенные вами изменения будут отображаться и при доступе через исходный объект!(То есть до тех пор, пока вы не замените один из этих объектов, что необходимо для неизменяемых классов, таких как String.)

Подкласс должен иметь доступ к защищенным методам суперкласса.

Если вы просто вызовете super.method() вместо mDelegate.method(), все пройдет;вы оба оборачиваете родительский класс и создавая его экземпляр.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top