【问题标题】:Hiding methods in subclass在子类中隐藏方法
【发布时间】:2014-12-01 22:04:51
【问题描述】:

我有一个带有一些实现方法的抽象超类。

是否可以在继承自该超类的子类中隐藏该超类的方法?我不想在某些子类中从超类中看到某些方法。最后但并非最不重要的一点是,是否可以更改子类中与超类中具有相同名称的方法的参数数量?

假设我们在超类中有一个方法public void test(int a, int b),但现在我想在子类中有一个方法public void test(int a),它调用超类函数并且超类中的方法不再可见。

【问题讨论】:

    标签: java inheritance methods method-hiding member-hiding


    【解决方案1】:

    是否可以在继承自该超类的子类中隐藏该超类的方法?

    如果您在超类中将方法设为私有,则它在子类中将不可见(或对其他任何人)。

    但是,如果您需要将基类中的方法公开,则无法通过例如用私有实现覆盖它来将其隐藏在子类中。 (您不能“降低可见性”,即在子类中从公共或受保护变为私有。)

    最好的解决方法可能是重写该方法并抛出运行时异常,例如UnsupportedOperationException

    是否可以更改子类中与父类中具有相同名称的方法的参数数量?

    不,您不能更改签名。您可以创建 另一个 具有相同名称和不同数量参数的方法,但这将是一个不同(重载)的方法,并且基类中的方法仍然可见。

    【讨论】:

    • 一种解决方法是在超类中创建方法protected,然后有两个实现。一个只是创建public 方法(即授予对父 API 的访问权限),而另一个创建调用父 API 的新方法。第二种类型在某种程度上隐藏了父 API(但子类仍然可以看到它们)。
    • 第二个问题的答案是正确的,但我认为它的措辞具有误导性。通过更改参数的数量和类型来重载方法名称是完全允许的。此外,对重载方法名称的访问限定符没有限制(前提是签名与另一个继承的方法不匹配)。但是,超类方法仍然可见。
    • 这不是改变参数的数量,而是添加另一个具有不同数量的参数的方法。
    • 我同意。但是,您的措辞可能会暗示新手不允许重载方法名称。
    • 好多了。重申基类方法仍然是可见的,这并没有什么坏处。
    【解决方案2】:

    不,您不能在孩子中隐藏公共方法,例如通过将方法设为私有。

    原因是有一个子类的实例,你可能总是将它转换为基类,并在那里调用方法。

    所以这种行为是合乎逻辑的。如果 API 变得太丑陋,要么重新设计类层次结构,要么创建一个新类。

    但是您可以覆盖该方法并

    /**
     * Use <code>test(a)</code> instead.
     * @param a.
     * @param b.
     */
    @Deprecated
    @Override
    public void test(int a, int b) {
        throw new UnsupportedOperationException("Use test(int) instead.");
    }
    
    public void test(int a) { // Overloaded method
        int b = ...;
        super.test(a, b);
    }
    

    可以重载一个方法:同名,不同的参数类型。

    【讨论】:

      【解决方案3】:

      Java 不支持降低可见性。

      有一种方法可以做这样的事情,但它很复杂:

      1. 您需要为父类型创建一个接口。这个接口不需要有方法。
      2. 您创建另一个新类型Delegate,它实现了方法public void test(int a, int b)
      3. 您删除了当前的父类型。
      4. 您创建了两个实现接口的新类型。一个将调用test(a,b) 委托给Delegate,另一个创建一个新方法test(a),该方法最终使用Delegate 实例。

      所以实现旧代码的类型对外界永远是不可见的(它可能是包私有类)。

      【讨论】:

      • 当然,那么新类型的对象将不再是基类的实例。
      • 这就是新类型实现相同接口的原因。正如我所说,它不是很好,不是很清晰,等等。
      • 抱歉——我的评论不清楚。原始基类具有某些方法,而新类型没有,这使得它们在编写客户端代码以使用基类的这些方法的情况下无法使用。您正在为与 OP 似乎面临的不同问题提出一个好的架构。
      • 将您共享的方法移动到界面中。正如我所说,这是一个笨拙的解决方案,但这取决于 OP 真正想要实现的目标。
      【解决方案4】:

      你不能完全隐藏超类的方法,它总是可以调用的,例如

        MyBase o = new MyClass();
        o.test(1, 2);
      

      但是,您可以以特定方式覆盖该方法:

      class MySuper {
        public void test(int a, int b) {; }
      }
      
      class MyClass extends MySuper {
        @Deprecated
        @Override
        public void test(int a, int b) {
          throw new UnsupportedOperationException("Do not call this method, call test(int a) instead!");
        }
      
        public void test(int a) { ; }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-08-15
        • 1970-01-01
        • 1970-01-01
        • 2011-09-14
        • 2017-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-13
        相关资源
        最近更新 更多