Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can’t we override a base class method with private extended class method?

class One {
    void foo() { }
}
class Two extends One {
    private void foo() { /* more code here */ }
}

Why is the above snippet of code wrong?

like image 439
Amol Aggarwal Avatar asked Dec 12 '22 15:12

Amol Aggarwal


2 Answers

I'm going to try to incorporate the ideas from the other answers to come up with a single answer.

First off, let's take a look at what's going on in the code.

A look at the code

The One class has a package-private foo method:

class One {
    // The lack of an access modifier means the method is package-private.
    void foo() { }
}

The Two class which subclasses the One class, and the foo method is overriden, but has the access modifier private.

class Two extends One {
    // The "private" modifier is added in this class.
    private void foo() { /* more code here */ }
}

The issue

The Java language does not allow subclasses to reduce the visibility of a method, field or class in a subclass, therefore, the Two class reducing the visibility of the foo method is not legal.

Why is reducing visibility a problem?

Consider the case where we want to use the One class:

class AnotherClass {
  public void someMethod() {
     One obj = new One();
     obj.foo();  // This is perfectly valid.
  }
}

Here, calling the foo method on the One instance is valid. (Assuming that the AnotherClass class is in the same package as the One class.)

Now, what if we were to instantiate the Two object and place it in the obj variable of the type One?

class AnotherClass {
  public void someMethod() {
     One obj = new Two();
     obj.foo();  // Wait a second, here...
  }
}

The Two.foo method is private, yet, the One.foo method would allow the access to the method. We've got a problem here.

Therefore, it doesn't make much sense to allow reduction of visibility when taking inheritance into account.

Links

  • Controlling Access to Members of a Class - Explanations of access modifiers from The Java Tutorials.
like image 164
coobird Avatar answered Dec 28 '22 10:12

coobird


The problem with this code is that if it were legal, Java wouldn't be able to respect the private modifier of foo if you accessed it indirectly through the One base class. For example, if I were to write

One obj = new Two();
obj.foo();

Then we'd be in trouble because we'd be calling the private method foo of Two indirectly, since when the compiler checks the line obj.foo() it looks at One to determine if foo is accessible, not at Two. The reason for this is that the compiler can't always tell what obj could be pointing at - if, for example, I write something like

One obj = Math.random() < 0.5? new One() : new Two();
obj.foo();

Then the compiler can't know whether obj points at a One or a Two. Consequently, it defers to One when checking access specifiers. If we were indeed allowed to mark foo private in Two, then the compiler would incorrectly allow us to call it through obj, which has type One, bypassing the guarantee that only the object itself can call private methods.

like image 25
templatetypedef Avatar answered Dec 28 '22 11:12

templatetypedef