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的包装类,也可以从要禁用的方法中抛出UnsupportedOperationException
exception。
如果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