Java,无法降低从对象inheritance的方法的可见性

继续这个问题: 为什么不能降低Java子类中方法的可见性?

我需要创建几乎与A类相同的B类,除了B不能做A可以做的某些事情。

作为一个懒惰的程序员,我试图inheritanceA ,只是为了迎接错误, B不能降低A方法的可见性。 咄!..

现在A是来自供应商的API,我的目的是封装此API,以便更容易使用。

我想知道解决这个问题的最佳做法是什么?

两种选择:

如果您需要B保持与A相同的接口(以便客户端代码可以使用这两个中的任何一个而不进行更改),您可以覆盖B “禁止”方法并让它们抛出UnsupportedOperationException 。 例如:

 public class A { public int allowedMethod() { ... } public int forbiddenMethod() { ... } } public class B extends A { public int forbiddenMethod() { throw new UnsupportedOperationException("Sorry, not allowed."); } } 

或者,如果您确实希望B的API成为A的API的子集,那么只需让B包含A的实例,并适当地委托方法调用。

  public class A { public int allowedMethod() { ... } public int forbiddenMethod() { ... } } public class B { private A a; public int allowedMethod() { return a.allowedMethod(); } } 

使用组合而不是inheritance 。

即类B持有对类A的引用,并在内部调用方法。

当需要更简单或更简单的界面时,使用外观。

您必须在外部接口周围创建自己的包装类(Facade Pattern)。

 interface Foreign { void dontWantThis(); void keepThis(); } interface/class MyForeign { void keepThis(); } 

然后,实现将具有可以引用调用的Foreign实例。

您可以构建一个提供简化API的包装类,也可以从要禁用的方法中抛出UnsupportedOperationExceptionexception。

如果B不能做所有可以做到的事情,你就不能把B视为A.

也许你需要一个包装器,而不是一个子类。

编辑:

所以你明白你永远不会减少子类方法的“可见性”:)。 抛出exception或不做任何事情都不会降低可见性,因此需要一个包装器。 有时,这种情况是设计糟糕的信号(有时只是)。

这与圆椭圆问题非常相关。

解决方案可能会使用“组合”而不是“干扰”。 您可以在类B中具有类型A的属性。然后仅公开B中要实际实现的那些方法

您可以考虑另一种选择。

假设你想减少某些类的API:

 public class LargeApi { public void doFoo() { ... } public void doBar() { ... } public void doBaz() { ... } ... ... } 

这样客户端只会暴露于doFoo方法(或者您更喜欢使用它们的任何方法):

 public interface ReducedApi { void doFoo(); } 

但是为了在预期的LargeApi的任何地方使用ReducedApi的实例,你需要一种方法来回到LargeApi(最好没有强制转换):

 public interface ReducedApi { void doFoo(); LargeApiClass asLargeApiClass(); } 

强制客户端使用新的简化API的示例实现可能如下所示:

 public class ReducedApiImpl extends LargeApi implements ReducedApi { // Don't let them instantiate directly, force them to use the factory method private ReducedApiImpl() { } // Notice, we're returning the ReducedApi interface public static ReducedApi newInstance() { return new ReducedApiImpl(); } @Override public void doFoo() { super.doFoo(); } @Override public LargeApi asLargeApi() { return this; } } 

现在,您的客户可以使用缩减的api来处理常见情况,但在需要时可以回到大型api:

 ReducedApi instance = ReducedApiImpl.newInstance(); instance.doFoo(); callSomeMethodExpectingLargeApi(instance.asLargeApi()); 

我会使用适配器模式。 http://en.wikipedia.org/wiki/Adapter_pattern