Java继承:覆盖或隐藏的方法

当一个类扩展另一个时,它继承了超类的所有方法和变量。 如果您在具有相同签名的子类中对其进行不同定义,那么方法和变量在子类中的使用可能会有所不同。 现在Oracle区分覆盖和隐藏(http://docs.oracle.com/javase/tutorial/java/IandI/override.html)。 它说一个实例方法覆盖它的超类的方法,而一个类方法隐藏它。 “隐藏和重写之间的区别具有重要意义,被调用的重写方法的版本是子类中的版本,被调用的隐藏方法的版本取决于它是从超类还是子类调用。

让我们假设我有2班是和可能。 是延伸也许。 也许有String a。

class Maybe {
    String a;
    public static void printOut() {
        System.out.println("Maybe");
    }
    public void printAndSet() {
        a = "Maybe";
        System.out.println(a);
    }

}
class Yes extends Maybe {
    public static void printOut() {
        System.out.println("Yes");
    }
    pubilc void printAndSet() {
         a = "Yes";
    }
}
class Print{
    public static void mail(String[] args) {
        Maybe m = new Maybe();
        Yes y = new Yes();
        Maybe.printOut();
        Yes.printOut();
        m.printAndSet();
        y.printAndSet();
}

我说:它会打印出可能是或许是的

但在阅读Oracle文章后,我认为它必须打印出来:

yes
yes
maybe
yes

因为实例方法会覆盖它的超类方法。

我确信自己对输出是正确的,但我也确信,甲骨文知道更好,所以我想我只是不理解这篇文章。 当我从一个超类的对象中调用一个实例方法时,它使用覆盖的方法并不是真的。 所以我不明白为什么要区分覆盖和隐藏! 有人可以帮忙吗?

编辑; 插入代码而不是描述类!


静态方法根本无法被覆盖。 它们不是多态调用的,因为它们不是在类的实例上作用,而是在类本身上作用。

如果调用Maybe.printOut() ,它将调用Maybe定义的静态printOut()方法。 在Yes定义的printOut()方法是无关紧要的:除了名称外,这两个方法没有任何共同之处。

请注意,您可以通过编写程序并执行它来确认或减弱您的疑虑。

隐藏方法的问题只发生在您开始调用对象实例的静态方法时。 这是非常糟糕的做法,绝不应该这样做。 如果你不尊重这条规则,并有以下几点:

Maybe m = new Maybe();
Maybe y = new Yes();

m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();

结果maybe maybe ,因为在静态方法的情况下,重要的不是对象的具体类型( MaybeYes ),而是它们的声明类型( MaybeMaybe )。


public class Parent {

    public String test(){
        return "p";
    }

    public static String testStatic(){
        return "sp";
    }
}


public class Child extends Parent {

    public String test(){
        return "c";
    }

    public static String testStatic(){
        return "sc";
    }
}

public class Demo{

    public static void main(String[] args) {

        Parent p =new Parent();
        Child c = new Child();
        Parent pc = new Child();

        System.out.println(p.test());
        System.out.println(c.test());
        System.out.println(pc.test());

            //Although this is not the correct way of calling static methods
        System.out.println(p.testStatic());
        System.out.println(c.testStatic());
        System.out.println(pc.testStatic());
    }
}

OUTPUT将是: - (静态方法vs实例方法)

p c c sp sc sp


根据你的例子举一个例子:

public class SO11720216 {
    static class Maybe {
        public static void hidden() { System.out.println("static maybe"); }
        public void overwritten() { System.out.println("instance maybe"); }
        public void inherited() { hidden(); }
        public void called() { overwritten(); inherited(); }
    }
    static class Yes extends Maybe {
        public static void hidden() { System.out.println("static yes"); }
        public void overwritten() { System.out.println("instance yes"); }
    }
    public static void main(String[] args) {
        Maybe m = new Maybe();
        Yes y = new Yes();

        m.called(); /* prints:
                       instance maybe
                       static maybe
                    */

        y.called(); /* prints:
                       instance yes
                       static maybe
                    */
        Yes.hidden(); /* prints: static yes */
        y.hidden(); /* bad style! prints: static yes */
    }
}

要将呼叫overwritten将由每个派生类覆盖。 所以每个方法都会使用属于当前对象的实现。 另一方面,对hidden的调用将始终使用定义类的实现。 因此Maybe.called将总是调用Maybe.hidden ,并且永远不会Yes.hidden 。 要调用Yes.hidden ,您必须从Yes的方法中或使用限定名称来执行此操作。

为了以不同的方式来表达:

  • 覆盖方法意味着无论何时在派生类的对象上调用该方法时,都会调用新的实现。
  • 隐藏一个方法意味着在这个类的范围内(例如在它的任何方法的主体中,或者在合格的时候hidden()对这个名字进行非限定的调用(例如我上例中的inherited()方法中的hidden()调用inherited()带有这个类的名字)现在将调用一个完全不同的函数,需要一个资格从父类访问同名的静态方法。
  • 也许你的困惑来自于你假设覆盖影响所有对该方法的调用,即使对于基类的对象也是如此。

    链接地址: http://www.djcxy.com/p/78799.html

    上一篇: Java Inheritance: Overwritten or hidden methods

    下一篇: Why is a singleton class hard to test?