简体   繁体   中英

Implementing a method that is present in both interface and abstract class in java

I am trying to understand what happens if a method is present in both an abstract class and an interface. Below, I posted a scenario that gives you a clear idea of what I am referring to.

interface act
{
    void read();
}

abstract class enact
{
    void read() {
        System.out.println("hello");
    }
}

public class second extends enact implements act  
{
    public void read() {

        // does method read() correspond to  Interface or abstract class?
    }
}

Surprisingly,there is no compilation error when I write this code. Any suggestions would be highly helpful.

I am just curious to know whether the method read() relates to interface or abstract class

Or neither, really. It depends on the apparent type in the context where you actually use it. Eg whether you do

enact example = new second();

or

act example = new second();

Both allow you to compile the code:

example.read();

because the read() method is defined in both apparent types, act and enact. But in both cases, it's the read() definition defined in the "second" class that really matters. That's what gets executed.

I am not sure what kind of problems you expect so I will try to show that there are no problems with this scenario.

You are calling methods from references like:

Second sc = new Second();//you should name your classes with upper-case
sc.read(); 

and this will execute code from Second class because that is type of object stored in sc reference (this is how polymorphism works - or to be precise dynamic binding ).

You could also create instance of Second class and pass it to reference of Act type (all types in Java should start with upper-case, including interfaces, and enums) like

Act act = sc;// or Act act = new Second();
act.read();

Since read() method is polymorphic (only final, private or static methods aren't) at runtime JVM will look for code to execute in class which instance is stored in art interface, so since it is instance of Second class code of read() from that class will be executed (if you would not override it in that class code inherited from Enact abstract class will be executed).

My understanding is as follows. Let's start by considering a simpler setting. Class Second is abstract, and implements two interfaces, Act and React. Both interfaces declare a non-default void read() method. In this case, Second inherits multiple declarations of the same method, no implementation, and the compiler is happy (JLS 8.4.8.4).

interface Act {

    void read();
}  

interface React {

    void read();
}  

public abstract class Second implements Act, React {
}

If one or both interface methods are default methods, we get a compiler error (JLS 8.4.8.4, 9.4.1.3), unless Second inherits an abstract read() method from a superclass (JLS 8.4.8.4), as in the following scenario, where Second actually ends up inheriting three read() methods.

interface Act {

    default void read() {}
}  

interface React {

    void read();
}

abstract class First {

    abstract void read();
}  

public abstract class Second extends First implements Act, React {
}

In the absence of such a superclass, Second must give an implementation of read(), thus preventing the inheritance of the conflicting methods (JLS 9.4.1.3). Of course, Second must do the same if all interface methods are abstract and we don't want to declare the class itself as abstract.

If Second does give a concrete implementation of read(), as in the following example, this method does not "relate" to one or the other of the interface methods: it simply overrides, and prevents the inheritance of, any and all superinterface methods with the same signature -- more precisely, with a signature which the signature of read() in Second is a subsignature of -- as if there were only one such method (JLS 8.4.8.1). (In some corner cases it may be impossible for a method to simultaneously satisfy all the contracts of the methods it is meant to override. James Gosling offers a nice example of this in section 4.3.2 of his -- and colleagues' -- The Java Programming Language .)

interface Act {

    void read();
}  

interface React {

    void read();
}  

public class Second implements Act, React {

    @Override
    public void read() {}
}

Your case is similar.

interface Act {

    void read();
}

abstract class Enact {

    void read() {}
}

public class Second extends Enact implements Act {

    @Override
    public void read() {}
}

The only real difference is that read() in Enact is a concrete method (the fact that Enact is abstract is irrelevant), but things don't change very much: the declaration in Second overrides both read() in Act and read() in Enact (JLS 8.4.8.1). At the same time, it is a valid implementation of the Act interface, so there is really no problem here.

Note that this code would compile even if Second did not override read(): Second would inherit read() from Enact, and the inherited method would be considered as an equally valid implementation of Act (JLS 8.4.8, 8.4.8.1, 9.4.1.3).

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