Vinayak Bansal
Vinayak Bansal

Reputation: 103

What is the use of having a less restricted method in a more restricted class in java?

Eg

class Abc{
   public void fun() 
    {
      System.out.println("public method") ;
    }
    @Override
   public String toString() 
    {
      // "has to be public method but the access is default because of the class access";
      return super.toString();
    }
    
}

In the above Eg - fun method access is public but the class access is default hence what is the use of having the method public rather than default because it cannot be access without creating object.

In the same way the toString method has to be public since (overriding cannot restrict the access). But it is already getting restricted since the class access is default

My Basic question is What is the use of having a less restricted method in a more restricted class?

Upvotes: 1

Views: 122

Answers (2)

John Bollinger
John Bollinger

Reputation: 181199

My Basic question is What is the use of having a less restricted method in a more restricted class?

There are several purposes related to inheritance and polymorphism. The biggest of those is probably that methods that override superclass methods or implement interface methods cannot be more restricted than the method they override. In this regard, I note that you express a possible misconception when you say:

the toString method has to be public since (overriding cannot restrict the access). But it is already getting restricted since the class access is default

That class Abc has default access does not prevent any other class from having references to instances of Abc or from invoking the public methods of that class. The declared type of any such reference will be a supertype of class Abc, but the implementation invoked will be that provided by Abc.

Additionally, there is the question of signaling intent. It is helpful to view the access specified for class members to be qualified by the access level of the class. Thus, declaring fun() to be public says that it can be accessed by everyone who can access an instance of Abc. This is somewhat useful in its own right, but it also turns out to be especially useful if the access level of the class is ever changed. If the class's designer chose member access levels according to this principle, then those do not need to be revisited under these circumstances.

Upvotes: 6

rzwitserloot
rzwitserloot

Reputation: 103637

On its face?

Absolutely no purpose whatsoever. It's measurable (you can use reflection to fetch a java.lang.reflect.Method object that represents that method, and you can ask it if it is public, and the answer would be 'yes', but it doesn't actually change how accessible that method is.

However, taking a step back and thinking about the task of programming in its appropriate light, which includes the idea that code is usually a living, breathing idea that is continually updated: Hey, your class is package private today. Maybe someone goes in and makes it public tomorrow, and you intended for this method to be just as public as the type itself if ever that happens.

Specifically in this case, you're overriding a method. Java is always dynamic dispatch. That means that if some code has gotten a hold of an instance of this class (Created with new Abc()), and that code is not in this package, that they can still invoke this method.

Let's see it in action:

package abc;

class Abc {
    @Override public String toString() { return "Hello"; }
}

public class AbcMaker {
    public Object make() { return new Abc(); }
}

Note that here AbcMaker is public and make() can be invoked just fine from outside code; they know what Object is, and Abc is an Object. This lets code from outside the abc package invoke and obtain Abc instances, even though Abc is package private. This is fine.

They can then do:

package someOtherPackage;

class Test {
    public void foo() {
        System.out.println(new AbcMaker().make().toString());
    }
}

And that would print Hello, as expected - that ends up invoking the toString defined in your package private class, invoked from outside the package!

Thus, we come to a crucial conclusion:

That toString() method in your package private class is ENTIRELY PUBLIC.

It just is. You can't override a method and make it less accessible than it is in your parent type, because java is covariant, meaning any X is a valid standin for Y, if X is declared as X extends Y. if Y has public toString, then X's can't take that away, as all Xs must be valid Ys (and Ys have public toString methods, therefore Xs must also have this).

Thus, the compiler is forcing you here. The banal reason is 'cuz the spec says so', but the reason the spec says this is to make sure you, the programmer, are not confused, and that what you type and write matches with reality: That method is public, it has to be, so the compiler will refuse to continue unless you are on the same page as it and also say so.

Upvotes: 2

Related Questions