Проблема с доступом в Java - PullRequest
1 голос
/ 07 декабря 2009

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

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.

Ответы [ 4 ]

3 голосов
/ 07 декабря 2009

Почему вы создаете отдельный экземпляр 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();
        }
    }
}

Edit2: Исходя из вашего комментария ниже, есть два подкласса 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 */
    }
}
2 голосов
/ 07 декабря 2009

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

Теперь FooWrapper может расширять PublicFoo и делать все что угодно.

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

0 голосов
/ 07 декабря 2009

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

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

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

0 голосов
/ 07 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...