Java Inheritance: Overwritten or hidden methods

When a class extends another, it inherits all methods and variables of the superclass. Both methods and variables can be used differently in the subclass, if you define it differently in the subclass with the same signature. Now Oracle distincts between overwriting and hiding (http://docs.oracle.com/javase/tutorial/java/IandI/override.html). It says that an instance method overwrites its superclass's method, while a class method hides it. "The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."

Lets assume I have 2 classes Yes and Maybe. Yes extends Maybe. Maybe has 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();
}

And I say: It will print out maybe yes maybe yes

But after I read the Oracle article I thought it would have to print out:

yes
yes
maybe
yes

Because the instance method overwrites its superclass method.

I'm quite sure I am right with the output, but I'm sure aswell, that Oracle knows better so I'm thinking I just didn't understand the article. It can't be true that when I call an instance method from an object of a superclass, that it uses the overwritten method. So I do not understand why to distinguish overwriting and hiding! Can someone help out?

Edit; Inserted code instead of describing the classes!


Static methods can't be overridden at all. They're not called polymorphically, since they don't act on an instance of the class, but on the class itself.

If you call Maybe.printOut() , it will call the static printOut() method defined in Maybe . The fact that there is also a method printOut() defined in Yes is irrelevant: those two methods have nothing in common, except their name.

Note that you could confirm or infirm your doubts by simply writing a program and executing it.

The problem with hiding methods only occurs when you start calling static methods on an instance of an object. This is very bad practice, and should never be done. If you don't respect this rule, and have the following:

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();

the result will be maybe maybe , because in the case of static methods, what counts is not the concrete type of the objects ( Maybe and Yes ), but their declared type ( Maybe and Maybe ).


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 will be: - (static method vs instance method)

p c c sp sc sp


Take the following example, based on your example:

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 */
    }
}

The call to overwritten will be overwritten by each derived class. So every method will use the implementation belonging to the current object. On the other hand, the call to hidden will always use the implementation of the defining class. Hence Maybe.called will always call Maybe.hidden , and never Yes.hidden . To call Yes.hidden , you'll have to do so from within a method in Yes , or using a qualified name.

To phrase this differently:

  • To overwrite a method means that whenever the method is called on an object of the derived class, the new implementation will be called.
  • To hide a method means that an unqualified call to that name (like the hidden() call in the inherited() method of my above example) in the scope of this class (ie in the body of any of its methods, or when qualified with the name of this class) will now call a completely different function, requiring a qualification to access the static method of the same name from the parent class.
  • Perhaps your confusion comes from the fact that you assumed overwriting to affect all calls to the method, even for objects of the base class.

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

    上一篇: Java中的动态方法查找

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