Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it good practice override methods with a higher visibility?

Answering this question: How to GUI - Using paintcomponent() to initialize a GUI and then to add GUI based on mouse I've stated this:

You don't override paintComponent() properly. This is a protected method, not public. If you add @Override annotation on this method then the compiler will complain.

But @peeskillet wisely pointed out this:

The compiler will not complain about public or protected with paintComponent. You can override with a higher visibility but not a lower one. public is higher than protected so there's no problem.

Which is certainly true. But now it arises this question: Is it good practice override with a higher visibility?

Addendum

Link to JComponent.paintComponent() javadoc.

Image of Netbeans not complaining at all:

enter image description here

like image 924
dic19 Avatar asked Jan 24 '14 16:01

dic19


People also ask

Can we change the visibility of method while overriding?

First, when you override methods in a subclass, the overriding method must be at least as visible as the overridden method. While it is possible to take a private method and override it with a public method in a subclass, the reverse is not possible; you can't override a public method with a private method.

Why would you want to override a method?

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides.

What are the basic principles to override a method?

Instance methods can be overridden only if they are inherited by the subclass. A method declared final cannot be overridden. A method declared static cannot be overridden but can be re-declared. If a method cannot be inherited, then it cannot be overridden.

Can we override an interface method with visibility other than public?

No. We cannot override an interface method if it's visibility is not public. And if it has its visibility as public then you can override it with the same method signature (i.e., with the same access specifier public) whenever you implement the interface to any class.


2 Answers

One reason to do this is if you have a method you need to override elsewhere in your project and the current scope does not allow you to. Typically when using default instead of protected.

By creating a new sub class in the right package elsewhere in your project with revised scope, you can then create an anonymous class in your code where you need it as you are now allowed to override the troublesome method instead of having to do with reflection (which makes for quite unreadable code).

This is also a reason for library classes never to be final because then you cannot do things like this.


EDIT: I was asked to elaborate on why this is relevant for Dependency Injection. I can only speak based on my own experiences, first with Guice and now with Dagger.

Dagger uses Constructor Injection which basically mean that a class will get all its dependencies provided as arguments to the constructor (and only there) and that the glue code binding this together is listed in a Dagger @Module. In this module it is usually very convenient to return a subclass of a library class augmenting with log statements or providing a custom toString() method. In order to actually DO this without reflection tricks the clasess cannot be final and you need to be able to override methods and to use fields in the superclass directly. Hence no final classes and both types need to be at least protected instead of private!

(and I can strongly recommend using Dagger because it moves the dependency resolving in the java compiler giving the IDE the information needed to help you resolve problems at compile time, instead of depending on magic in the runtime in the wild. I am still amazed at the insight in the Java ecosystem the Dagger designers had to even get this idea and then realize it)

like image 58
Thorbjørn Ravn Andersen Avatar answered Oct 02 '22 10:10

Thorbjørn Ravn Andersen


From Java Tutorial, Controlling Access to Members of a Class:

If other programmers use your class, you want to ensure that errors from misuse cannot happen. Access levels can help you do this.

  • Use the most restrictive access level that makes sense for a particular member. Use private unless you have a good reason not to.
  • Avoid public fields except for constants. (Many of the examples in the tutorial use public fields. This may help to illustrate some
    points concisely, but is not recommended for production code.) Public fields tend to link you to a particular implementation and limit your flexibility in changing your code.

This advice is aimed to reduce coupling:

To achieve the best encapsulation (information hiding) you should always declare methods with the least visibility that works. In small programs there's really no problem, but in large programs this problem of excessive coupling is very serious. Coupling occurs when one part depends on the specific implementation of another. The more coupling there is the more costly it becomes to make changes because too much code depends on specific implementations. This causes software rot - a program becomes progressively less usable because it can't be easily upgraded.

So, increasing visibility is actually not a good idea. Such code could couse trouble in future development and maintenance.

like image 24
Mikhail Avatar answered Oct 02 '22 09:10

Mikhail