简体   繁体   中英

Whose method gets overridden when a derived class extends a base class and at the same time implements an interface?

Case 1:

I have an Interface Inter.java:

interface Inter
{
        void abcd();
}

A base class:

class Base
{
        void abcd()
        {
                System.out.println("Base abcd");
        }
}

A Derived class:

class Use extends Base implements Inter
{
        void abcd()  //intentionally not using public 
        {
                System.out.println("Use abcd");
        }
        public static void main(String[] args)
        {
                Use u = new Use();
                u.abcd();
        }
}

Now I compile it:

gyan@#ns:~/Desktop$ javac Inter.java Base.java Use.java 
Use.java:3: error: abcd() in Use cannot implement abcd() in Inter
    void abcd()
         ^
  attempting to assign weaker access privileges; was public
1 error
gyan@#ns:~/Desktop$ 

That means the overridden method abcd() in the class Use is from the implemented interface "Inter" and not from the base class "Base".

Case 2:

We have a file Test.java containing following codes:

interface Ab
{
        void run();
}

class A extends Thread implements Ab
{
        public void run()
        {
                System.out.println("class A");
        }
        public static void main(String[] args)
        {
                A a = new A();
                Thread t = new Thread(a);
                t.start();
                System.out.println("main method");
        }
}

When we execute it we got:

gyan@#ns:~/Desktop$ java A
main method
class A
gyan@#ns:~/Desktop$

Since t.start() executed the method run(), that means method run() of the class Thread got overridden. But in the case 1 method abcd() of the interface "Inter" got overridden.

In case 1: Whose method abcd() is overridden in class Use? Class Base or interface Inter? Error says we are overriding the abcd() of interface Inter. But in case 2: It seems that we are not overriding the method run of interface Ab. Because we can execute the run() method by calling t.start(). Which is only possible if we are overriding the run() of class Thread.

The method in your class overrides the base class method and implements the interface, at the same time.

Overriding a method is not exactly the same as implementing an interface :

  • Overriding a method from a superclass means you are replacing its implementation. If you are not providing an overriding method, the implementation from the superclass (which can be empty) will be used.
  • When implementing an interface method, you are providing code for a simple declaration (without any implementation). If you declare a not-abstract class as implementing an interface, but don't provide an implementation for every method of the interface, compilation fails. This is less true in Java 8, where you can optionnally provide a default implementation in interfaces, but in this case any implementation from a superclass would win.

Implementations and overrides of a method can always extend its visibility, but not decrease it. This means :

  • a package-private (default visibility), or protected method in a superclass can be made public in the subclass
  • but a public method in a superclass cannot be made package-private or protected in the subclass.

Methods in an interface are always public, even if the "public" modifier is not specified in the interface. Hence, their implementations must also be public => that's the error you get in your case 1

As a side note, in your case 2, you are using threads wrong. Do not subclass Thread. Instead, create a class implementing the Runnable or Callable interface, and submit it to a thread pool (see classes in java.util.concurrent, or for a quick test use java 8's ForkJoinPool.commonPool().submit(myTask) .

Both. Method overriding depends on the name and signature of the method not where it is defined. If defined on more than one ancestor, it overrides both. Note: If defined as public in one and protected in another, it'll become public.

In the Inter interface, void abcd(); is the definition of an abstract method. All abstract methods are inherently public.

From { Defining an Interface },

All abstract, default, and static methods in an interface are implicitly public, so you can omit the public modifier.

So, while Inter said that abcd() was public , the actual implementation in Use is saying that the implementation of abcd() is package-private , which is a weaker access privilege. This should address your comment "//intentionally not using public" .
Traditionally, abcd() should also use the annotation @Override (although it is not a hard requirement).

In your second example, Thread class provides a concrete implementation of run() . Given that A#run() is public, you have satisfied the requirement imposed by interface Ab regarding access specifiers. Then, A#run() went on to override Thread#run() - which is exactly how we would expect inheritance to behave.

To summarize, we just saw the difference between extends (extending or overriding class methods) and implements (contract that the given class provides an implementation for all the methods states in the interface). { This answer } goes into more depth about this and is an excellent read.

Let me know if any part of this answer needs more clarity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM