Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Hiding Overriding and the modifier final

I couldn't find a question like mine, so I hope it's not a duplicate one.

Again it's about overriding and hiding. I think - but I might be wrong - I understood both.

The following code behaves as expected, both methods have been hidden. method1 because it is a private method and private methods can't be overridden only hidden, method2 because it's static and static methods can't be overridden, they can only be hidden.

public class Child extends Parent { 
    public void method1(){System.out.println("child");}     
    public static void method2(){ System.out.println("static child");}  
}

class Parent{
    private void method1(){ System.out.println("parent");}      
    public static void method2(){ System.out.println("static parent");}

    public static void main(String[] args){
            Parent p = new Child();
            p.method1(); //prints out "parent"
            p.method2(); //prints out "static parent"
    }
}

If I read the specs it says:

http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.3.3

A method can be declared final to prevent subclasses from overriding or hiding it.

If I change method1 in the Parent class to "final"

private final void method1(){ System.out.println("parent");}

Everything works fine. edit start: I expected an compiler error saying that final methods can't be hidden, but that didn't happen. :edit end

Question no 1: does that mean only static methods can be hidden? In the book I'm reading (OCA study guide, Jeanne Boyarsky and Scott Selikoff page 252) they clearly say that a private method was hidden.

Then I changed method2 in the Parent class to

public final static void method2(){ System.out.println("static parent");}

Now the compiler does complain, the error says "Child cannot override method2()" which is pretty confusing because I thought I tried to hide a method.

Question no 2: Shouldn't it be "Child cannot hide method2()"?

edit start: I am well aware that no overriding happens here, but as the mentioned specs point out: the modifier final prevents methods to be overridden or hidden, that's why I put it in the title. :edit end

like image 532
whoCares Avatar asked Feb 03 '16 13:02

whoCares


People also ask

Can final methods be hidden?

No, the Methods that are declared as final cannot be Overridden or hidden. For this very reason, a method must be declared as final only when we're sure that it is complete.

What is the difference between overriding and hiding in Java?

In method overriding, when base class reference variable pointing to the object of the derived class, then it will call the overridden method in the derived class. In the method hiding, when base class reference variable pointing to the object of the derived class, then it will call the hidden method in the base class.

What is the difference between hiding method & overriding method?

For Method overriding override keyword is being used. In case of Method Hiding new keyword is used to define new implementation in child class. In Method Overriding the implementation type of the method is of object type. However on other hand implementation type of method in Method hiding is of reference type.


2 Answers

Question 1

Question no 1: does that mean only static methods can be hidden?

Parent.method1() was not visible in nor inherited by Child simply by virtue of being private. So Child.method1() didn't override or hide Parent.method1(), it merely created a new method in Child that had the same name, parameters and return type.

See http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.3:

Note that a private method cannot be hidden or overridden in the technical sense of those terms. This means that a subclass can declare a method with the same signature as a private method in one of its superclasses, and there is no requirement that the return type or throws clause of such a method bear any relationship to those of the private method in the superclass.

Question 2

Question no 2: Shouldn't it be "Child cannot hide method2()"?

Yes, you are correct. It should be "hide". Per the JLS (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2),

If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible to code in C.

"Hiding" is what static methods do to static methods. "Overriding" is what instance methods do to instance methods. The two can't be mixed: a static method can't override or hide an instance method, and an instance method can't override or hide a static method.

BTW, my Eclipse compiler gives a similar error message: "Cannot override the final method from Parent"

like image 92
Erick G. Hagstrom Avatar answered Sep 22 '22 03:09

Erick G. Hagstrom


Well, I'm quite new to java, but I'll try to answer.

The difference resides in the fact that you're using different access level modifiers: you're using private on method1() of Parent class and public on method1() on Child class. In fact, you're not hiding the method as it is not the same method. The private modifier specifies that the member can only be accessed in its own class, therefore, you're using a new method when you declare method1() on Child class. Even though, child inherits all methods from Parent (as it extends it), private methods are not inherited. In the case of method2(), as it is declared public, it is inherited by Child class and can be hidden.

More about it (Taken from oracle tutorials):

Private Members in a Superclass

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.

A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.

EDITED: Question 2:

You hide a static method, not a final one. Only static ones can be hidden as in here:

class SuperClass {
    static void display() {
        System.out.println("Super");
    }
}

class SubClass extends SuperClass {
    static void display() {
        System.out.println("Sub");
    }
}

public class Test {
    public static void main(String[] args) {
        // Prints "Super" in console
        SuperClass sup = new SubClass();
        sup.display();

        // Prints "Sub" in console
        SubClass sub = new SubClass();
        sub.display();
    }
}

You use the final keyword in a method declaration to indicate that the method cannot be overridden by subclasses. So, if you change it, you are overriding it and, therefore, compiler says:

overridden method is static,final (notice the final).

Compiler complains about it because you're not longer hiding it. As you declared it final, you're overriding it. It will give you the same error, if you do not use the static modifier on the Child class as you'll be trying to override what it is no longer static. Hiding is only used when the static method hides another static method. If you try:

  1. nonstatic method "hides" static one: that is override.
  2. final method "hides" static one: that is override.

In those cases, you're not trying to hide anymore (because hiding is use only on static) but you're trying to override.

like image 24
Cherenkov Avatar answered Sep 24 '22 03:09

Cherenkov