20

Why derived class overriding method should not be more restrictive than base class in java.Why compiler throws error?can you please anyone explain reason for that?

Jaydeep Rajput
  • 3,605
  • 17
  • 35
Rose
  • 331
  • 2
  • 4
  • 8

4 Answers4

31

The point is that a caller who only knows about your superclass should still be able to use any instance of the subclass that it's given. Consider this situation:

public class Super
{
    public void print()
    {
        System.out.println("Hello!");
    }
}

public class Sub extends Super
{
    @Override
    void print() // Invalid
    {
        System.out.println("Package access");
    }
}

Now from a different package, imagine we had:

public void printSuper(Super x)
{
    x.print();
}

and we called that with:

printSuper(new Sub());

What would you expect that to do? You're overriding the method, so it should print "package access" - but then that means you're calling a package access method from a different package...

Basically, this is just one example of the Liskov Substitution Principle in action. You should be able to treat any instance of a subclass as an instance of the superclass, and it's hard to see how that fits in with making things more restrictive in a subclass.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 5
    you could cite Liskov Substitution Principle http://en.wikipedia.org/wiki/Liskov_substitution_principle – Scorpion Apr 24 '13 at 06:33
  • If you don't want the user to be able to use the function in your own implementation, you can always override it with an empty version. This way the interface to the class doesn't break. Of course you have to decide if such an approach makes sense, depending on the expectation of a a given function. – Devolus Apr 24 '13 at 06:35
  • 2
    @JonSkeet I was being lazy and didn't to write in a new answer just to illustrate the point so I just added a reminder - knowing your reputation I shouldn't have doubted that you would add it :-) – Scorpion Apr 24 '13 at 06:51
6

You can not make access modifier more restrictive, because that would violate the basic rule of inheritance that a subclass instance should be replacable in place of a superclass instance.

For e.g Suppose that Person class has getName public method which is being used by many classes(including non-sub classes).But somebody just added Employee as subclass of Person and getName in Employee is protected which should be accessed only by sub-classes then the previous code would start breaking and Employee would not be replacable to Person object.

Hence java has decided to impose this restrcition.

Jaydeep Rajput
  • 3,605
  • 17
  • 35
1

Consider below example

class Mammal {
    public Mammal readAndGet() throws IOException {//read file and return Mammal`s object}
}

class Human extends Mammal {
    @Override
    public Human readAndGet() throws FileNotFoundException {//read file and return Human object}
}

And if we execute below code

Mammal mammal = new Human();
Mammal obj = mammal.readAndGet();

And we know that for compiler mammal.readAndGet() is getting called from the object of class Mammal but at, runtime JVM will resolve mammal.readAndGet() method call to a call from class Human because mammal is holding new Human().

Method readAndGet is defined public in Mammal and in order to make it less restrictive in class Human we will need to either remove the access specifier (making it default) or make it protected or private.

Now suppose

  • If we define readAndGet as default or protected in Human but Human is defined in another package
  • If we define readAndGet as private in Human

We know JVM will resolve readAndGet method call at runtime but the compiler is unaware of that and in both cases, the code will compile successfully because for compiler readAndGet is getting called from class Mammal.

But in both cases at runtime JVM will not be able to access readAndGet from Human because it will be restricted due to restrictive access of readAndGet in Human class.

And also we can not be sure of who will be extending our class in future and in what package he will be doing that and if that guy makes the overriding method less restrictive JVM might not be able to call the method and code will break at runtime.

So to avoid this uncertainty, assigning restrictive access to the overriding method in the child class is not allowed at all.

There are other rules as well which we need to follow while overriding the methods and you can read more on Why We Should Follow Method Overriding Rules to know the reasons.

Naresh Joshi
  • 4,188
  • 35
  • 45
1

The overriding message should not be more restrictive then the overridden method because an instance of the child class should always be able to be used in a place where an instance of the superclass is expected. But if a method is more restrictive, it may not be accessible if the call is coming from another class or package. For example, imagine this:

//File Number 1
public class Human {
    public int age = 21;
    public int getAge() {
        System.out.println("getAge() method in Human");
        return age;
    }
}

//File Number 2
public class Teacher extends Human {
    public int getAge() {
        System.out.println("getAge() method in Teacher");
        return age;
    }
}

//File Number 3
public class Characteristics {  
    public static void showAgeOfObject(Human human) {
        human.getAge();
    }

    public static void main(String[] args) {
        Human human = new Human();
        Teacher teacher = new Teacher();

        showAgeOfObject(human);     
        showAgeOfObject(teacher);
    }
}

Now if both getAge() methods are public, this will be displayed

getAge() method in Human
getAge() method in Teacher

But if getAge() in Teacher was private, this would throw an error because we are in a different class which therefore cannot access the method.

primChareka
  • 281
  • 3
  • 6