Как реализовать шаблон декоратора для класса Java с защищенными методами - PullRequest
7 голосов
/ 28 июля 2011

Подкласс вне пакета не может получить доступ к защищенным членам в экземплярах родительского класса (только в экземплярах самого подкласса или его подклассов).Ссылка JLS: http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.2

Вот пример.Существует существующий класс, выглядящий следующим образом:

package package1;
public abstract class BaseImplementation {

    public String getResource1() {
        return processTemplate1(getBaseUrl());
    }

    public String getResource2() {
        return processTemplate2(getBaseUrl());
    }

    // Kind of 'Template Method' pattern.
    protected abstract String getBaseUrl();
}

Таким образом, намерение состоит в том, чтобы написать декоратор, как показано ниже:

package package2;
public class ImplementationDecorator extends BaseImplementation {
    private BaseImplementation delegate;

    public ImplementationDecorator(BaseImplementation delegate) {
        this.delegate = delegate;
    }

    @Override
    protected String getBaseUrl() {
        return trackServer + "?redirect=" + delegate.getBaseUrl();
    }
}

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

Поэтому вопрос заключается в том, как декорировать такие экземпляры защищенными методами, не используя «грязные» приемы, такие как отражение или помещение подкласса в пакет.с тем же именем, что и у родительского класса.

Есть также примеры того же самого в самом языке Java (например, javax.security.auth.login.ConfigurationSpi), и в случаях, которые я обнаружил в Java, используется доступ из того же пакета.

Ответы [ 3 ]

3 голосов
/ 28 июля 2011

Здесь вы пытаетесь сделать перехватывать поведение, более или менее приватное в отношениях между типом BaseImplementation и одним из его производных типов & ndash; здесь, ваш экземпляр "делегата", который вы ' Я хотел бы украсить в вашем ImplementationDecorator классе. Автор BaseImplementation никогда не ожидал, что кто-то захочет попасть туда посередине, а автор типа, производного от BaseImplementation, не ожидал, что туда войдут другие абоненты, кроме BaseImplementation.

Вместо этого, шаблон, который вы ищете, будет выглядеть примерно так, что, боюсь, вы не сможете модернизировать, если не владеете участвующими классами:

public interface URLProvider
{
  String getBase();
}


public final class BaseImplementation
{
  public BaseImplementation(URLProvider provider)
  {
    if (null == provider)
      throw new NullPointerException();
    this.provider = provider;
  }


  public String getResource1()
  {
    return processTemplate1(provider.getBase());
  }


  public String getResource2()
  {
    return processTemplate2(provider.getBase());
  }


  private final URLProvider provider;
}

Имея это в виду, если бы кто-то написал реализацию типа URLProvider, его было бы легко декорировать, потому что теперь метод URLProvider#getBase() является общедоступным.

Теперь вы можете сказать, ну, разве это не то же самое, что просто поменять ваш BaseImplementation#getBaseUrl() метод на публичный, а не защищенный? Не совсем. Здесь проект подтверждает & mdash; или даже предупреждает & mdash; экземпляр URLProvider - это возможность, которую можно использовать из любого места.

0 голосов
/ 28 июля 2011

Это не очень хороший ответ (я ответил в комментарии), но есть способ обойти:

public abstract class BaseImplementation {

    (...)

    protected String getBaseUrl(BaseImplementation other)
    {
        return other.getBaseUrl();
    }
}

public class ImplementationDecorator extends BaseImplementation {
    private BaseImplementation delegate;

    (...)

    @Override
    protected String getBaseUrl() {
        return trackServer + "?redirect=" + getBaseUrl(delegate);
    }
}
0 голосов
/ 28 июля 2011

Защищенные функции должны быть видны. Для получения доступа к ним не нужно использовать «грязные уловки».

Вот что способны защищенные члены:

Доступно длявсе классы в одном пакете, а также доступны всем подклассам класса, которому принадлежит защищенная функция. Этот доступ предоставляется даже подклассам, которые находятся в другом пакете, чем класс, которому принадлежит защищенная функция.

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