简体   繁体   中英

Can subclass inherit interface implementation from parent unrelated to the interface

This is kind of quirk or corner case. Consider this example:

interface I {
    void foo();
}

class B {
    public void foo() {}
}

class C extends B implements I {}

With my compiler (OpenJDK in Linux) it compiles and the following works:

I c = new C();
c.foo();

Why? Is it intentional and backed by the language standard? How the runtime knows to follow first "down" from I to C and then "up" from C to B ? While that would be clear in case B implements I , it seems counter intuitive given B unrelated to I .

Well, in the example you mentioned c is an instanceof the class C . Hence, it would require to have it's own method foo() .

Now, C has gotten all public (and default?) methods from B and foo() happens to be one that is (technically) present, thanks to B . Hence, the requirement that the interface placed on C , to have its own foo() method, is fulfilled by B s foo() .

I don't think the down from I to C, and up from C to B is relevant here, in the way you mentioned it.

EDIT:

All evidence points to the fact that the compiler has at-hand, a list of implemented functions, both that are in the given class, and 'virtual' ones that are extended from the parent class.

As a result, if the aforementioned class is implementing some interface, both extended and the classes own functions are tallied against the ones that needed to be implemented (because of the interface).

When you written class C extends B implements I following will happen From JLS 8.4.8 Inheritance, Overriding, and Hiding :

A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:

  • m is a member of the direct superclass of C.
  • m is public, protected, or declared with package access in the same package as C.
  • No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.

A class C inherits from its direct superclass and direct superinterfaces all abstract and default (§9.4) methods m for which all of the following are true:

  • m is a member of the direct superclass or a direct superinterface, D, of C.

  • m is public, protected, or declared with package access in the same package as C.

  • No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.

  • No concrete method inherited by C from its direct superclass has a signature that is a subsignature of the signature of m.

  • There exists no method m' that is a member of the direct superclass or a direct superinterface, D', of C (m distinct from m', D distinct from D'), such that m' from D' overrides the declaration of the method m.

So its inherits abstract method from interface I and a concrete methods with same signature from class B .

It doesn't really "follow" like you think. C inherits all non-private methods from B , and C can do whatever it wants with those methods; override them, use them to implement interfaces (if the method is public ), invoke them, etc.

So the method foo is a method of C , even if it came by the method by inheriting it from B . And a class can expose any of its public methods through an interface .

The first thing to note is the common effect of extending B and implementing I . The common effect or the obvious outcome in java is that you can have only one method with a particular name, datatype and parameters(same type and equal in number) .

Any method which has the same name and different number of arguments would be a case of method overloading. But in your case, it's pretty simple that you need to implement and define the abstarct method foo() in I in a concrete subclass which in this case is C .

It's not compulsory to redefine every method in the superclass but it becomes compulsory when you are implementing an interface. So Java considers this method foo() in the class C as the inherited method from the interface I . Otherwise you would have seen an error asking you to redefine the method foo() which is inherited from the interface.

Unknowingly this also becomes a case of method overriding when you consider the superclass B . Since the foo() method in C has the same kind of declaration as in B and I (which it should according to the standards, rules and to satisfy the rules of implementing an interface), it easily satisfies the interface as well as overrides the method in B .

In your case, you are also overriding the method foo() in class B .

So one condition as well as a complementary offer (overriding) is being satisfied.

In the end, class C has just one foo() method which overrides the method in B as well as satisfies the condition of implementing interface I .

An example:

Let the method foo() be defined (in C ) as:

void foo()
{
System.out.println("Hello");
}

Create 2 objects in C as follows:

B b=new C();
C c=new C();

Call foo() :

b.foo();
c.foo();

Ouput: Both prints Hello .

Conclusion: foo() in C satisfies the interface (no error seen) and also overrides the method foo() in B .

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