Reputation: 1534
I have one class and one interface:
public interface A {
public void getNum();
}
public class B {
public void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
protected void getNum() {
System.out.println("3");
}
}
Now my question is, why this code is giving compilation error and how can we avoid it. Is there any way in which we can override this method in class C?
Upvotes: 4
Views: 3431
Reputation: 124225
From Java Language Specification:
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.
- ...
Notice that you are trying to override public
method getNum()
inherited from class B
(and also from interface A
) with new one that has protected
access modifier. It means that you are trying to reduce visibility of this method which according to specification is incorrect.
To be able to override this method you need to use public
access modifier with your new version of that method.
Why you cant reduce visibility? Take a look at below code which uses your classes but is placed inside some other package and ask yourself "how should this code behave?".
package my.pckage;
import your.pckage.A;
import your.pckage.C;
public class Test{
public static void main (String[] args){
C C = new C();
c.getNum();// ERROR: Test class doesn't have access to `c`s protected method.
// Why should it have, Test doesn't extend C.
A a = (A)c;// Lets try using other reference
a.getNum();// Should `a` have access to method that is protected in `C`?
// If yes, then what is the point of declaring this method
// protected if all I would have to do to get access to it is
// casting instance of C to A interface?
}
}
Upvotes: 13
Reputation: 863
First of all scope should be from lower to higher while you are overriding method in Java. scope of subclass method should be high then super class for e.g
Valid Overriding
class B {
protected void getNum() {
System.out.println("4");
}
class C extends B {
public void getNum() {
System.out.println("3");
}
InValid Overriding
class B {
public void getNum() {
System.out.println("4");
}
class C extends B {
protected void getNum() {
System.out.println("3");
}
Your second problem is you have created two public class which is not valid you can create only one public class in your java file.
Upvotes: 6
Reputation: 21
As stated, only one public class can be used per file. So, to have them all public, one must create three separate .java files. I will write the code up below, as well as detailing how to override the method to use the correct version of it in each case.
One may always have methods with the same name, but for overriding, they must have different argument lists. This is one of the compiler errors, you have three methods with the same argument lists, namely none. You may create and call the method with the correct argument list to achieve the desired result.
A.java:
package stackOverflow.tests; // Sample package for visibility
public Interface A {
public void getNum(int a); // Method takes a single integer argument
}
B.java:
package stackOverflow.tests;
public class B {
protected void getNum(int a, int b) { // Method takes two integer arguments, differing in the argument list but equal in name
System.out.println("4");
}
}
C.java:
package stackOverflow.tests;
import stackOverflow.tests.A; // Importing both classes to use their methods
import stackOverflow.tests.B;
public class C extends B implements A {
public void getNum(int a, String x) { // Takes an integer and a string argument
System.out.println("3");
}
public void getNum(int a) {
//Do nothing, as in A.java, this code is necessary to be able to override the method.
}
public static void main(String[] arguments) { // Sample main method for implementation
C c = new C(); // Instantiating class C
int test = 0; // Initializing two integer variables and one String variable
int test2 = 0;
String test3 = "";
c.getNum(test); // takes one integer, using getNum() from A.java
c.getNum(test, test2); // takes two integers, using getNum() from B.java
c.getNum(test, test3); // takes an integer and a String, using getNum() from C.java
}
}
Output:
4
3
As seen in the code above, the argument lists define which version of the method is used. As a side tip, the definition getNum(int a)
is no different from getNum(int b)
, so this would result in it not compiling.
Upvotes: 2
Reputation: 6276
The explanation by Pshemo is perfectly right that you can not reduce visibility of overridden
or the interface
functions.
Lets take an exapmle
class B
{
protected void getProtected1()
{
System.out.println("4");
}
protected void getProtected2()
{
System.out.println("4");
}
public void getPublic1()
{
System.out.println("4");
}
public void getPublic2()
{
System.out.println("4");
}
}
class C extends B
{
@Override
private void getPublic1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
@Override
protected void getPublic2() //COMPILATION ERROR :Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
@Override
private void getProtected1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
@Override
public void getProtected2() // NO ERROR IT MEANS YOU ARE ALLOWED TO INCREASE THE VISIBILITY
{
System.out.println("3");
}
}
From the above example it is clear that you are not allowed to decrease the visibility of function in any case.
In your question you are trying to implement the interface
function and we know interface
in Java has rules that,
public
& abstract
are permittedpublic
, static
& final
are permittedAs thumb of rule, you can never decrease the visibility, of overridden
or implemented methods or variables and for interface
it is always public
(if visibility is concerned) so those should always be public
in implemented classes.
Upvotes: 2
Reputation: 81
A java class file can have only one public class or interface. Change the visibility of the interface and the defined class to default level or declare it in separate files.
Only public and abstract modifiers can be applied to interface methods. The class implementing the interface cannot change the visibility of the method (we cannot change it from public to protected).
Upvotes: 1
Reputation: 2294
In order to get this working you can do something like this since there can be only one public class per file and the file name should be the same name as that of the class
public class HelloWorld{
public static void main(String []args){
C obj=new C();
obj.getNum();
}
}
//interface
interface A {
public void getNum();
}
class B {
protected void getNum() {
System.out.println("4");
}
}
class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
output: 3
Upvotes: 1
Reputation: 68935
When you implement an interface you need to compulsorily override it to provide concrete implementation of function(unless the class implementing the interface is abstract). In your case you are implementing an interface which make you implement getNum()
function and due to overriding class you have another function with same signature which is not allowed. So you get compilation error.
Possible solution : You can make B as an interface.
Upvotes: 5
Reputation: 431
Fix the typos and try again ;)
public interface A {
public void getNum();
}
public class B {
protected void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
Upvotes: 6