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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4041157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:30:26  来源:igfitidea点击:

Java, Cannot reduce the visibility of the inherited method from object

javaoopapi

提问by Rosdi Kasim

Continuing from this question: Why can't you reduce the visibility of a method in a Java subclass?

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

I need to create class Bthat is almost identical to class A, except that Bcannot do certain things that Acan.

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

Being a lazy programmer as I am, I tried to inherit A, only to greet with error that Bcannot reduce the visibility of Amethods. Duh!..

作为一个懒惰的程序员,我试图继承A,结果却遇到了B无法降低A方法可见性的错误。呸!...

Now Ais an API from a vendor, my intention is to encapsulate this API so that it is easier to use.

现在A是一个厂商的API,我打算把这个API封装起来,方便使用。

I wonder what is the best practice to work around this?

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

回答by Grodriguez

Two options:

两种选择:

If you need Bto keep the same interface as A(so that client code can use any of the two without changes), you can override "forbidden" methods in Band have them throw an UnsupportedOperationException. For example:

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

Or, if you really want the API of Bto be a subset of the API of A, then just have Bcontain an instance of A, and delegate method calls appropriately.

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

    public class A
    {
        public int allowedMethod() { ... }
        public int forbiddenMethod() { ... }
    }

    public class B
    {
        private A a;

        public int allowedMethod()
        {
            return a.allowedMethod();
        }
    }

回答by William

Use Composition rather than Inheritance.

使用组合而不是继承

i.e. class B holds a reference to a class A and internally calls methods on it.

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

回答by willcodejavaforfood

A facade is used when one wants an easier or simpler interface to work with.

当人们想要一个更简单或更简单的界面来使用时,就会使用外观。

You would have to create your own wrapper class (Facade Pattern) around your foreign interface.

您必须围绕外部接口创建自己的包装类(外观模式)。

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

interface/class MyForeign
{
    void keepThis();
}

The implementation would then have a instance of Foreign that it can refer calls to.

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

回答by sinuhepop

If B can't do all thing A can, you couldn't treat B as an A.

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

Maybe you need a wrapper, not a subclasse.

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

EDIT:

编辑:

So you'd understand you'll never reduce the "visibility" of a subclass method :). Throw an exception or do nothing is not reduce the visibility, therefore you need a wrapper. Sometimes, this situation is a signal of a bad design (only sometimes).

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

This is very related to circle-ellipse problem.

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

回答by rsp

You can build a wrapper class offering a reduced API, or you can throw an exception like UnsupportedOperationExceptionfrom the methods that you want to disable.

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

回答by madhurtanwani

The solution would probably use "composition" over "inhertence". You could have a property in class B, of type A. Then expose only those methods in B that you want to actually implement

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

回答by Matthew Madson

Another option you might consider.

您可能会考虑的另一种选择。

Say you want to reduce the API of some class:

假设您想减少某个类的 API:

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

Such that clients would only be exposed to say the doFoo method (or any method you'd prefer them to use instead):

这样客户只会暴露于 doFoo 方法(或您希望他们使用的任何方法):

public interface ReducedApi {
  void doFoo();
}

But in order for instances of the ReducedApi to be used anywhere the LargeApi is expected, you need a way to get back to the LargeApi (preferably without casting):

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

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

An example implementation forcing clients to use your new reduced API might look like the following:

强制客户端使用新的简化 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;
  }
}

Now your clients can use your reduced api for the common case, but cast back to the large api when needed:

现在您的客户可以将您的简化 api 用于常见情况,但在需要时转换回大型 api:

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

回答by punkers

I would use the adapter pattern. http://en.wikipedia.org/wiki/Adapter_pattern

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