包外的子类不能访问父类实例上的 protected 成员(只能访问子类本身或其子类的实例)。 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()
在基类中具有 protected 访问权限,即使是子类也无法在父实例上访问它。
所以问题是如何使用 protected 方法装饰此类实例,而不使用“肮脏”的技巧,例如反射或将子类放入与父类同名的包中。
在 Java 语言本身中也有相同的示例(例如 javax.security.auth.login.ConfigurationSpi
),在我发现的 Java 案例中 - 从同一个包访问是用过。
最佳答案
您在这里尝试做的是拦截行为,这种行为在类型 BaseImplementation
与其派生类型之一之间的关系中或多或少是私有(private)的——在这里,您的“delegate"实例,你想在你的 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()
方法更改为公共(public)方法而不是 protected 方法吗?不完全的。在这里,设计承认——甚至警告——URLProvider
实例是一种可以在任何地方使用的功能。
关于java - 如何使用 protected 方法为 Java 类实现装饰器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6863117/