Overriding and weaking access modifiers - java

According to the JLS 8.4.8.1
An instance method m1, declared in class C, overrides another instance
method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same
package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2),
such that m3 overrides m2.
This doesn't appear to contradict the following code:
public class Main {
public void f() { }
public static class A extends Main {
protected void f() { }
}
public static void main(String[] args) {
}
}
DEMO
But it's not compiling, even though the overridden version of the method f() has the protected access modifier, as said in the second point of the rule I provided. What's wrong?

The justification for this is provided lower in the JLS, in 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.
Note that the section you've quoted in your question essentially states "the method's access modifier in the base class must not be private", and doesn't relate to the overriding method's access modifier at all.

You cannot override a method with more restrictive access modifier. The method f() was declared with access modifier public but you are trying to override it with protected modifier which is more restrictive. Change
public static class A extends Main{
protected void f(){ }
}
to
public static class A extends Main{
public void f(){ }
}

Related

java extend static method, can't compile, why?

class Base {
public static void f(){}
}
class Derived extends Base{
private static void f(){}
}
the Derived.f()'s modifier must be public, if it's private ,the compiler say
"attempting to assign weaker access privileges; was public".
I can't understand! Why compiler not allow us to do that?
Static methods can't be overridden , those can only be hidden by the subclasses and accessability of a method has nothing to do with hiding.Only instance methods can be overridden but methods are hidden or overridden based on the signatures and in both the cases signatures should be same.You can't reduce the accessibility of an inherited method whether it's hidden or overridden.
It's a fundamental principle in OOP, that you are not allowed to assign weaker access modifier (here is private) in subclass than in superclass (here is public) when you override methods.
This is irrelevant to the Liskov Substitution Principle (LSP), that is a concept in Object Oriented Programming that states: functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
So it could be:
public class Base {
private static void f() {
}
}
class Derived extends Base {
public static void f() { // as well as protected, default, private
}
}

Why am I getting method overriding error?

THis is my superclass:
class Superclass {
int a=89;
final static void m( int p){
System.out.println("Inside superclass");
}
static void n(){
system.out.print("superclass");
}
}
This is my subclass::
class Subclass extends Superclass {
int a=90;
static void m( int p){
System.out.println("Inside subclass");
}
static void n(){
system.out.print("subclass");
}
}
Main class:
class main {
public static void main(String[] args) {
Subclass.m(89);
new Subclass().n();
}
}
the problem is that i cannot understand why Javac is giving me overriding error in static method..an P.S plzz elaborate that all rules for overriding are also valid for hiding. like
The new method definition must have the same method signature (i.e.,
method name and parameters) and the same return type. Whether
parameters in the overriding method should be final is at the
discretion of the subclass method's signature does not encompass the
final modifier of parameters, only their types and order.
The new
method definition cannot narrow the accessibility of the method, but
it can widen it The new method definition can only specify all or
none, or a subset of the exception classes (including their
subclasses) specified in the throws clause of the overridden method in
the superclass
my error is:
run:
Exception in thread "main" java.lang.RuntimeException: Uncompilable
source code - m(int) in javaapplication3.Subclass cannot override
m(int) in javaapplication3.Superclass overridden method is
static,final at javaapplication3.Subclass.m(JavaApplication3.java:18)
at javaapplication3.min.main(JavaApplication3.java:25) Java Result: 1
also i want to ask if static members called from classname to resolve whicch version of method is executed when method is hidden by subclass extending the superclass
what if i make anonymous object and then call method then how the compiler determines which version of method should be called.
in above code in main class i type this: new Subclass().n();
how does the compiler know subclass version of method should be called even if i am not providing the type of reference variable
From the JLS 8.4.3.3:
A method can be declared final to prevent subclasses from overriding or hiding it.
Static methods with the same signature from the parent class are hidden when called from an instance of the subclass. However, you can't override/hide final methods.
The keyword final will disable the method from being hidden. So they cannot be hidden and an attempt to do so will result in a compiler error. There is a nice explanation on this on Javaranch.
What you are observing here is in accordance with JLS 8.4.3.3 which states that:
It is a compile-time error to attempt to override or hide a final
method.
You are trying to override final static void m method in subclass , which is not permitted by Java compiler.

Inheritance having protected class

This is a code sample of inheritance while the code functions fine.I am unable to understand the output of this code kindly explain it to me.
class R {
private void S1() {
System.out.println("R:S1");
}
protected void S2() {
System.out.println("R:S2");
}
protected void S1S2() {
S1();
S2();
}
}
class S extends R {
private void S1() {
System.out.println("S:S1");
}
protected void S2() {
System.out.println("S:S2");
}
}
public class Inheritance {
public static void main(String srgs[]) {
new S().S1S2();
}
}
The output is:
R:S1
S:S2
Why is the first call made to,R class' S1 while second to S class' S2.
R.S1 is private, so it's not called polymorphically, and S.S1 doesn't override it.
R.S2 is protected, so S.S2 overrides it, and when you call S2 on an instance of S2 (even if it's only statically known to be an instance of R), S.S2 will be called.
From section 8.4.8.1 of the JLS:
An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2), such that m3 overrides m2.
Note how m2 can't be private.
In R, S1 is private and so cannot be overridden. The call to S1 in R#S1S2 therefore always calls R#S1. The S1 in S is totally unrelated. [Side note: you need better names.]
But S2 is not private so it can be overridden - and it is.
Java VMs can get good performance gains out of knowing that private functions cannot be overridden. And nothing, not even a descendant class, should be affected by the private details of a class.

java accidential implicit interface implementation

Recently came across an interesting feature, which, though, can result in a unexpected output of Eclipse "add unimplemented methods" feature. What is the "googl-able" name of the language concept behind this "occasional implicit implementation"?
I wouldn't expect the code below to compile but it did and is working
interface CallmeIfc {
public void callme();
}
class CallmeCode {
public void callme() {
// implementation
}
}
class CallmeImpl extends CallmeCode implements CallmeIfc {
// empty class body
}
public static void main(String[] args) {
CallmeIfc me = (CallmeIfc) new CallmeImpl();
me.callme(); // calls CallmeCode.callme()
}
In CallmeImpl, the public callme() method is inherited from CallmeCode, so CallmeImpl respects the contract defined in the CallmeIfc.
Then, in your main() method, polymorphism allows you to assign a subclass instance (CallmeImpl) to a superclass or superinterface reference - in this particular case, the "me" reference, of type CallmeIfc (you have a typo here, BTW).
Actually this looks like a compiler bug to me: The Java Language Specification writes:
An instance method m1 declared in a
class C overrides another instance
method, m2, declared in class A iff
all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either
m2 is public, protected or declared with default access in the same package as C, or
m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3 overrides m2.
In your case, the first condition is not satisfied: The method callme is declared in class CallMeCode, which is not a subtype of CallmeIfc.
Edit: Bobah is right, the Spec distinguishes between implementing and overriding. In fact, it actually mandates the observed behaviour:
Unless the class being declared is
abstract, the declarations of all the
method members of each direct
superinterface must be implemented
either by a declaration in this class
or by an existing method declaration
inherited from the direct superclass,
because a class that is not abstract
is not permitted to have abstract
methods
The Spec does not explain why.
Although CallmeCode class doesn't implement the CallmeIfc interface, it provides the necessary implementation. It is as if class CallmeCode implements the interface. It would have worked also with this code:
interface CallmeIfc {
public void callme();
}
class CallmeCode implements CallmeIfc {
public void callme() {
// implementation
}
}
class CallmeImpl extends CallmeCode implements CallmeIfc {
// empty class body
}
In your case this is fine because class CallmeCode has a method callme. If the method would have been named different it wouldn't compile.

Redefining static method in child class

I would like to know the reason why this is first allowed in Java (or oops in general)
I remember that the static methods are common for both parent and child class
public class Redefine extends Parent{
public static void test () {
}
}
class Parent{
public static void test () {
}
}
Q1 : Since Overriding is not supported for static methods , how can both classe contain same methods ?
Q2 : If change the method in static to throw an exception not defined its not compiling.
why is the case. Its obviously not overriding so i should be allowed to throw new exceptions right ?
public class Redefine extends Parent{
public static void test () throws Exception{
}
}
A1:: static method are per-class. They have nothing to do with inheritance hierarchies in terms of polymorphism. So calling Parent.test() will call the parent method, while calling Redefine.test() will call the child.
A2: JLS 8.4.8 writes:
If a class declares a static method m, then the declaration m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class.
A method declaration must not have a throws clause that conflicts (§8.4.6) with that of any method that it overrides or hides; otherwise, a compile-time error occurs.
you arent overriding it, you are hiding it
http://faq.javaranch.com/java/OverridingVsHiding
what exception are you getting?
Q1: Static methods are not overridden, so these are two different methods with the same signature. One is called with Parent.test(), the other is called with Redefine.test()
Q2: Your method seems valid. What error do you get?

Categories