Why can I override a protected method with public method? - java

The Java compiler doesn't complain when I override a protected method with a public method. What's really happening here? Is it overriding or hiding the parent method since the parent method has lower visibility?

A sub-class can always widen the access modifier, because it is still a valid substitution for the super-class. From the Java specification about Requirements in Overriding and Hiding:
The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.
If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.

From the point of view of an external class, the public method is just a new method, not an overriding method, since the external class could not access the protected method anyway.
On the other hand, lowering the visibility is not allowed because the external class can always use a reference of the type of a super-class to reference an object of the sub-class and call the same method.

The visibility only affects external accessibility. Being a public method any external class can call it.
Access level of the overriding method doesn't affect visibility of the original method. After override, with any access levels, the original method can only be accessed by calling super in the subclass.

Related

Why doesn't java allow to assign weaker access privileges to static methods in a child class?

I understand why java doesn't allow to set weaker access privileges for overridden methods, but why is it the same for static methods? I mean, these methods only hide each others, right? So what's the problem from the encapsulation point of view?
P.S.
I know that there are 5 rules for hiding a method
The method in the child class must have the same signature as the method in the parent
class.
The method in the child class must be at least as accessible or more accessible than the
method in the parent class.
The method in the child class may not throw a checked exception that is new or
broader than the class of any exception thrown in the parent class method.
If the method returns a value, it must be the same or a subclass of the method in the
parent class, known as co-variant return types.
The method defined in the child class must be marked as static if it is marked as
static in the parent class (method hiding). Likewise, the method must not be marked
as static in the child class if it is not marked as static in the parent class (method
overriding).
But after all, I don't get the idea from the encapsulation prospective
The same rules are valid and for method hiding
https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.3
Static methods have special access permissions that allow friend access to members within a instance. For example, you could have a static method called create that creates a default instance of the class and directly modifies data within the instance without using instance properties or instance methods (just for a usage example, not necessarily a usage recommendation).
Because of this special access, lower access permissions to the static methods could allow you to create an object in a state that you could not otherwise use, or modify an object in an unpredictable and non-encapsulated way.
This is only a minor annoyance for most user-defined classes, but allowing this when sub-classing e.g. containers could expose serious undefined behavior problems.

Reducing the visibility of a static method

I know that a child cannot reduce the visibility of a non-static method and I understand why it is so.
I've read however that "static method can be hidden through its redeclaration". I however do not understand how this could be achieved in Java.
Is this really possible? If yes, how to do that (code example) and why was it introduced (it seems to contradict the principle of non-reducing the visibility of the interface)?
The short answer is: no, it is not possible. You have mixed up some terminology. Hiding has nothing to do with accessibility (which is what you are really asking about, not visibility, which is related to scope and shadowing and is discussed in Chapter 6 of the Java Language Specification (JLS)).
Now for the longer answer. The term overriding applies to instance methods, while the term hiding applies to class (static) methods. From the Java Tutorial topic Overriding and Hiding Methods:
The distinction between hiding a static method and overriding an instance method has important implications:
The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
Some of the other answers here provide incorrect examples about method hiding, so let's go back to the JLS, this time to §8.4.8:
Methods are overridden or hidden on a signature-by-signature basis.
That is, to override or hide a method in the parent class, the subclass must define a method with the same signature—basically, the same number and type of arguments (although generics and type erasure makes the rules a little more complicated than that). There are also rules about return types and throws clauses, but those seem irrelevant to this question.
Note that you can define a method in a subclass with the same name as a method in the parent class (or in an implemented interface) but with different number or type of arguments. In that case, you are overloading the method name and neither overriding nor hiding anything; the subclass method is a new method, pretty much independent of the inherited method(s). (There is an interaction when the compiler has to match methods to method calls, but that's about it.)
Now to your question: the terms accessibility and hiding (as well as visibility) are independent concepts in Java. There is, as you put it, a "principle" that there is simply no way for a subclass to reduce the accessibility of an inherited method. This applies regardless of whether you are overriding an instance method or hiding a class method. From the JLS §8.4.8.3:
The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.
If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.
In summary, the fact that a static method can be hidden has nothing to do with changing the accessibility of the method.
Based on hagubear's valuable comments, it seems that the author of a statement meant hiding a method through overloading it with a method having the same declaration.
Quoting this link:
We can declare static methods with same signature in subclass, but it
is not considered overriding as there won’t be any run-time
polymorphism. (...) If a derived class defines a
static method with same signature as a static method in base class,
the method in the derived class hides the method in the base class.
Thus, defining a method in a child class having exact same declaration effectively hides the original method in child. However, as in case of fields, casting to the parent will restore the original access.
Sample code:
public class Test {
public static void main( String[] args ) {
B b = new B();
A a = b;
b.f(); // "Access somewhat denied"
a.f(); // "f()"
}
}
class A {
public static void f() {
System.out.println("f()");
}
}
class B extends A {
// *must* be public
public static void f() {
System.out.println("Access somewhat denied");
}
}
So I created a trivial test; IntelliJ indeed rejected it... and Yes, I know "it's a tool...but one I trust". In any case, I went to javac, which emitted the same ERROR:
Error:(...) java: ...Concrete.java:5: doSomethingStatic() in
...Concrete cannot override doSomethingStatic() in
...Base; attempting to assign weaker access privileges; was public
Based on this, and our skepticism in general, I suggest the error is in your documentation.
Below is my sample code, fairly definitive I think. It barfs at the protected.
public class Base
{
public static void doSomethingStatic(){}
}
public class Concrete extends Base
{
protected static void doSomethingStatic(){}
}
It can be hidden by an overloaded redeclaration in a derived class:
class Base
{
public static void doSomethingStatic(){}
}
class Derived extends Base
{
public static void doSomethingStatic(String arg){}
}
but only hidden to people who try to access it via the derived class.

Java: Forcing Not to Override

I have a super class with a final method
public final void foo(){ ... }
No you cannot do it.
Overriding a method in subclass with its superclass method marked final is not possible
. You can add a method with different signature
The purpose of final keyword applied to a method is that it doesn't allow subclass method to override it.
The main purpose of final is to prevent from overriding.So, you can not override final methods.
Still you can overload final methods.
You can't override the final super method.but you can overload it.
Make a method final only if it has an implementation that should not be changed and it is critical to the consistent state of the object.
You can't. The final keyword is there to prevent this.
See final methods in Java on Wikipedia.
It’s not clear why you have to have the same name. Either it’s intended to be a different method, then it can have a different name without problems or you are trying to do some sort of overriding you claimed not to do.
If your subclass needs an interface implementation which interferes with that method consider an inner class for that interface implementation.
Otherwise a method in the subclass does not override a superclass method with the same name if either:
it has different parameter types
the superclass method is private
the superclass method is package-private and the subclass resides in a different package

Method Overriding of diffrent Return type to void

let's say we have this method
public class Animal {
public void eat() { }
}
and on another class that extends Animal has this method
public String eat(){}
is this considered as method overriding? because I've heard that you can use different return types in method overriding providing they have the same method arguments
This is neither overloading , nor overriding ! It is compilation error .
In Java it is possible to define two or more methods within the same class that share the same name, as long as their parameter declarations are different. When this is the case, the methods are said to be overloaded, and the process is referred to as method overloading.
Following are rules of method overriding in java which must be followed while overriding any method. private, static and final method can not be overridden.
1)Method signature must be same including return type, number of method parameters, type of parameters and order of parameters.
2)Overriding method can not throw higher Exception than original or overridden method. This rule only applies to checked Exception in Java, overridden method is free to throw any unchecked Exception.
3)Overriding method can not reduce accessibility of overridden method , means if original or overridden method is public than overriding method can not make it protected.
You can only change the return type to a subclass of the original return type.
All answers are correct from a technical point of view because Void is a class in Java that no other class can extend and when methods are overridden the return-type has to be a sub-type of the original type (parentReturnType.isAsignableFrom(overriddenReturnType)).
But from a practical point of view the question is still valid and it would have made sense to make an excuse for the special case void. The only value a variable of the type Void can hold is null. Further no variable can have the primitive type void. Finally you can not compile this code:
Void result = object.notify();
So in the end it would have made sense to specify Java differently when 1.5 was introduced and allow overriding void return types with any other type.
Therefore the only reasonable answer is IMHO it is not possible because Java was designed such that this is not allowed.
This not correct Code, as two methods with same name should return same value, only arguments can be differents
Overriding is having same method with same arguments in the subclass
Overloading having same method name with different argumens
The return type of a method is not part of that method's signature.
When you call eat() on the subclass, java looks at the signature you provided (eat with no parameters) and starts looking for a method with this signature, starting in the class of the instance type of the object you call it on (and searches through its ancestors if it fails to find it).
So, methods called on a subclass will always run the overridden methods (they're found first).
A critical 'point' of OO (specifically polymorphism) is that a subclass can be passed in where the superclass was expected.
If a method wants to call the superclass' eat() method and get a void, but you passed a subclass into that method of which eat() returned a String; you can see that method will call the subclass' eat and get an unexpected value.
You can see why this could be a problem. :I
So, overriding methods must return the same type or a subclass of the type returned by the parent.
(Similar principles apply as to why you can return a subclass; I'll let you think about it c: )
It's neither overriding nor overloading, it creates compilation error.
Two methods with same name, different param numbers or different type of params known as overload method, return type may be same or different. It may be in same class or parent, child classes.
Two methods having same param numbers, same types, same return types but one is in parent class and other is in child class are known as overrided methods.

Why my overriding method of toString() has to be public?

I am new to Java and I am learning the basics. I was studying the toString method and how to override it in my own classes. I am just wondering why has toString to be public? is it because it is defined so in the Object class?
From official Oracle documentation:
Modifiers
The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.
This because inheritance creates an IS-A relation between two classes, for which the Liskov substitution principle must be valid. Without having the previous constraint that would be impossible to enforce.
Think about it: You subclass Gizmo with MyGizmo. This means that any place that a Gizmo can be used, you can use a MyGizmo in it's place. If some program does gizmoObject.toString() then that should work even if gizmoObject is not a Gizmo but a MyGizmo.
In particular, toString is used for printing & dumping objects and needs to be accessible on all objects.
When you override any method, the visibility of the override must be at least as visible as the base method.
When you override any method, the visibility of the override must be equal or more than the visibility of the base method
When overriding a method, you should declare the visibility of overridden method as the the one in the base class or wider.
Here is a note about the overriding rules I wrote it myself as a reference to me:
/* Access Modifiers */
1- Access modifier in child should be same or greater (the sequence:
public - protected - default (package-private) - private). Access
modifier in parent should not be private. If a child don't have access
to the parent's method, then overriding the method without the
#Override annotation will consider it as a new method.
/* Return Types */
2- Return type in child should be the same class or sub-class.
/* Exceptions */
3- If the parent's method throws checked exception, then the child's
method can: a- throw the same exception or sub-class. b- not to
throw any exceptions. c- throw runtime exceptions.
4- If the parent's method throws unchecked exception, then the child's
method can: a- not to throw any exceptions. b- throw runtime
exceptions.
5- If the parnet's method does not throw exception, then the child's
method can: a- not to throw any exceptions. b- throw runtime
exceptions.
Because you are overriding a method, you must define it as the prototype method or more than that.
when you override an sub class method visibility must be wider than parent class.
Wider to strict order:
public
default
protected
private

Categories

Resources