2

The question has been put up to discuss around the term hiding which is associated with static methods in java. Whenever a static method with the same signature is defined in the parent and the child class, the child class method is said to have hidden the method in the parent class. My question is around the usage of hiding, as we know static methods would be accessed by the class name or if we try to create a reference (which is a bad practice), method would be called based on the reference type. So how does hiding comes into picture, take example of below code:

public class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
}

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod(); // prints The static method in Animal
    }
}

Can someone please explain how child method has hidden the parent method here? (parent method is being called using parent reference, so how does hiding comes into picture)

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
greenHorn
  • 497
  • 1
  • 5
  • 16
  • 1
    Did you mean `myAnimal.testClassMethod();`? – ernest_k Apr 28 '18 at 08:15
  • Not sure if I understand you correctly, but this is a case of static binding in Java. All final, static and private methods and variables use static binding and are bonded by compiler. Static binding uses Type information for binding (in this case Animal). – aarnaut Apr 28 '18 at 08:20
  • Relevant documentation at https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2 – Jagrut Sharma Apr 28 '18 at 08:28
  • @RobinGreen: my question is more around the usage of the term hiding, probably not around where method hiding is used, not a duplicate of the question being asked before – greenHorn Apr 28 '18 at 08:47
  • @JagrutSharma: i have referred the documentation and have explained the method hiding concept in the question, my question is more around the term method hiding – greenHorn Apr 28 '18 at 08:48
  • nevertheless I believe the top answer to my proposed duplicate question does answer your question. – Robin Green Apr 28 '18 at 08:49
  • I did go through the answer that you had mentioned, it tells about the concept of method hiding, probably does not talk about why it is hiding – greenHorn Apr 28 '18 at 09:00
  • what did you mean by *"why IT is hiding"*? – Andrew Tobilko Apr 28 '18 at 09:50

4 Answers4

1

How has the child method hidden the parent method here?

As you said, by defining a static method with the identical signature.

How does hiding comes into the picture?

Cat.testClassMethod();

Some may expect the invocation of the parent method here (by analogy with polymorphism). But the idea of hiding by class methods is different:

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 (§6.6) to code in C.
...
A hidden method can be accessed by using a qualified name or by using a method invocation expression (§15.12) that contains the keyword super or a cast to a superclass type.
...

class Super {
    static String greeting() { return "Goodnight"; }
    String name() { return "Richard"; }
}
class Sub extends Super {
    static String greeting() { return "Hello"; }
    String name() { return "Dick"; }
}
class Test {
    public static void main(String[] args) {
        Super s = new Sub();
        System.out.println(s.greeting() + ", " + s.name());  // Goodnight, Dick
    }
}

JLS 10 - 8.4.8.2. Hiding (by Class Methods)

This example is perfect to show the difference between overriding and hiding. At the same time, it is a bad practice demonstration - calling static methods on an instance.

I will try to make it clear by providing another example.

Since public static methods are inherited, the following snippet

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
}

class Cat extends Animal {
    public static void main(String[] args) {
        // Cat: I don't have own method, probably I inherited it from the parent.
        //      O, yes. I can call it. 
        Cat.testClassMethod();
    }
}

prints

The static method in Animal

Now we're going to add testClassMethod to Cat.

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
}

class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }

    public static void main(String[] args) {
        // Cat: I have two version of the method: mine and the inherited one.
        //      The caller specified my class name, so he wanted my version. 
        //      I will call my method hiding the parent method.
        Cat.testClassMethod();

        // If he wanted Animal's version, he would write
        Animal.testClassMethod();

        // or (DON'T DO THIS)
        ((Animal)new Cat()).testClassMethod();
    }
}
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
1

This demonstrates exactly why it's a bad practice to intend to hide a static method. The method is chosen statically, at compile time, without any consideration for the actual instance type.

I suppose the take home phrase should be "hiding is not overriding... and don't do it", to mean that Java doesn't even look at the object/instance (only looking at the declared type):

Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testClassMethod(); //bad to do, but you can see it uses the declared "Animal" class

Cat.testClassMethod(); //Uses method in Cat
myCat.testClassMethod(); //Uses method in Cat

((Animal) null).testClassMethod(); //Uses Animal method, doesn't look at instance
((Cat) null).testClassMethod(); //Uses Cat method, doesn't look at instance

Now the interesting part: what if you remove the method from Cat? All of these invocations will still work, using the Animal method, which means that:

  • It's a very bad practice to hide static methods
  • It's equally bad to use class instances to invoke static methods, because in the case of hidden methods, it's easy to be misled...

To answer the question: hiding is illustrated with Cat.testClassMethod() or myCat.testClassMethod(), which invokes the static method based on the declared type. When there's no testClassMethod() in Cat, Java calls the parent's.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • There is no "actual instance type" in play when you call a static method. – Robin Green Apr 28 '18 at 08:28
  • @RobinGreen Yes, that's right... Am I missing something? – ernest_k Apr 28 '18 at 08:36
  • In the code in the question, there is no instance type. But you refer to it in your answer. That doesn't make sense, in context. – Robin Green Apr 28 '18 at 08:37
  • @RobinGreen Right, did that advisedly. I expanded the context of invoking on a class to include invoking on an instance reference. How would that not make sense to someone who reads the answer? – ernest_k Apr 28 '18 at 08:41
  • @ErnestKiwele: thanks for the explanation. Probably for me the term hiding is misleading, that is the reason i had put up the question, if we know at compile time which method would be called(based on the declared type) how does it hides. – greenHorn Apr 28 '18 at 09:01
  • 1
    Another way to look at it if we are calling the parent method using instance variable and instance variable being constructed as P p = new child(); then in that sense it hides the functionality. Does this statement holds true? – greenHorn Apr 28 '18 at 09:03
  • 1
    @greenHorn Exactly, "hiding" is confusing because it deviates very much from "overriding". It's seen as hiding *because when you reference the child class with the same method name, then the parent's method doesn't apply anymore", and instances never even come into play at all, which can be very confusing... – ernest_k Apr 28 '18 at 09:06
  • 1
    @greenHorn I would say: when it comes to static methods (in parent or child or otherwise), don't even look at instances. Just look at the declared data type, or static types (because even `null` being cast will get the static type's method to run). – ernest_k Apr 28 '18 at 09:08
0

All final, static and private methods and variables use static binding and are bonded by compiler. Static binding uses Type information for binding (in this case Animal).

So, in your case myAnimal.testClassMethod(); will print the static method in Animal because declared type is Animal.

aarnaut
  • 507
  • 6
  • 17
  • my question is more around the term method -hiding, i understand that static method and variables uses static binding. As i have illustrated in my example, i wanted to understand how a child method hides a parent method. – greenHorn Apr 28 '18 at 08:45
  • I wouldn't say that child hides parent, but the other way around. For example, if you did `Animal animal = new Cat(); animal.testClassMethod();`, it would call the method of the type (in this case parent class). – aarnaut Apr 28 '18 at 08:53
  • i understand how static method works, probably the term hiding is misleading then, since we know at compile time which method would be called – greenHorn Apr 28 '18 at 09:03
  • If you didn't implement the same static method in `Cat`, then `Cat.testClassMethod()` would invoke the `Animal` one. Since you did implement the exact same method, it calls the one in cat and therefore hides the parent method. – aarnaut Apr 28 '18 at 09:12
  • _If you didn't implement the same static method in Cat, then Cat.testClassMethod() would invoke the `Animal` one - agreed because in that case it would be calling the inherited method of the parent class, but when both of the methods are present in parent and child class and child method is being called using Child Class reference, in that case how does hiding comes in as we know child class method would be invoked – greenHorn Apr 28 '18 at 09:19
  • As you said, maybe hiding is the wrong term in this case. I would guess that it also targets code readability. If you had a static import, or somehow ommitted the class instance before the method (maybe directlye call it in child class), you would not know which method is called aka the child method would hide the parent method. But in any case, method hiding is probably not the right term in this case. – aarnaut Apr 28 '18 at 09:57
0

static methods don't take part in dynamic binding (polymorphism).

static methods aren't overritten, static methods are hidden by the subclass.

someone who calls Cat.testClassMethod() might expect the behaviour of Animal.testClassMethod()

So Cat.testClassMethod() is hiding Animal.testClassMethod()