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

时间:2010-10-28 08:42:48

标签: java oop api

继续这个问题:Why can't you reduce the visibility of a method in a Java subclass?

我需要创建与B类几乎完全相同的类A,但B无法执行A可以执行的某些操作。

作为一个懒惰的程序员,我试图继承A,只是为了问候B无法降低A方法的可见性。杜!..

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

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

8 个答案:

答案 0 :(得分:18)

两个选项:

如果您需要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();
        }
    }

答案 1 :(得分:9)

使用Composition rather than Inheritance

即。 B类包含对A类的引用,并在其上内部调用方法。

答案 2 :(得分:4)

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

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

interface Foreign
{
    void dontWantThis();
    void keepThis();
}

interface/class MyForeign
{
    void keepThis();
}

然后,实现将有一个Foreign实例,它可以引用调用。

答案 3 :(得分:3)

如果B不能做所有的事情,你就不能把B视为A。

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

修改

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

这与circle-ellipse problem非常相关。

答案 4 :(得分:2)

您可以构建一个提供简化API的包装类,或者您可以从要禁用的方法中抛出UnsupportedOperationException之类的异常。

答案 5 :(得分:1)

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

答案 6 :(得分:1)

您可以考虑另一种选择。

假设你想减少某些类的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());

答案 7 :(得分:0)

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