简体   繁体   English

子类可以从与接口无关的父类继承接口实现吗

[英]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:使用我的编译器(Linux 中的 OpenJDK)进行编译并执行以下操作:

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 ?运行时如何知道首先“向下”从IC然后从“向上”从CB While that would be clear in case B implements I , it seems counter intuitive given B unrelated to I .虽然在B implements I情况下这会很清楚,但鉴于BI无关,这似乎违反直觉。

Well, in the example you mentioned c is an instanceof the class C .好吧,在你提到的例子中, cclass C一个instanceof Hence, it would require to have it's own method foo() .因此,它需要有自己的方法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 .现在,C 已经从B获得了所有公共(和默认?)方法,而foo()恰好是(技术上)存在的方法,这要归功于B Hence, the requirement that the interface placed on C , to have its own foo() method, is fulfilled by B s foo() .因此,放置在C上的接口具有自己的foo()方法的要求由Bfoo()

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.我不认为从 I 到 C 和从 C 到 B 的下降在这里是相关的,就像你提到的那样。

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 :当您编写class C extends B implements I将遵循JLS 8.4.8 继承、覆盖和隐藏

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:类 C 从其直接超类继承所有满足以下条件的超类的所有具体方法 m(静态和实例):

  • m is a member of the direct superclass of C. m 是 C 的直接超类的成员。
  • m is public, protected, or declared with package access in the same package as C. m 是公共的、受保护的或声明为具有与 C 相同的包中的包访问权限。
  • No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.在 C 中声明的任何方法都没有作为 m 签名的子签名(第 8.4.2 节)的签名。

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:类 C 从其直接超类和直接超接口继承所有抽象和默认(第 9.4 节)方法 m,对于以下所有情况都为真:

  • m is a member of the direct superclass or a direct superinterface, D, of C. m 是 C 的直接超类或直接超接口 D 的成员。

  • m is public, protected, or declared with package access in the same package as C. m 是公共的、受保护的或声明为具有与 C 相同的包中的包访问权限。

  • No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.在 C 中声明的任何方法都没有作为 m 签名的子签名(第 8.4.2 节)的签名。

  • No concrete method inherited by C from its direct superclass has a signature that is a subsignature of the signature of m. C 从其直接超类继承的具体方法没有一个签名是 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.不存在作为 C 的直接超类或直接超接口 D' 的成员的方法 m'(m 与 m' 不同,D 与 D' 不同),使得来自 D' 的 m' 覆盖了方法 m.

So its inherits abstract method from interface I and a concrete methods with same signature from class B .所以它继承了interface I抽象方法和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; CB继承所有非私有方法, C可以对这些方法做任何想做的事情; override them, use them to implement interfaces (if the method is public ), invoke them, etc.覆盖它们,使用它们来实现接口(如果方法是public ),调用它们等。

So the method foo is a method of C , even if it came by the method by inheriting it from B .所以方法fooC的方法,即使它是通过从B继承的方法而来的。 And a class can expose any of its public methods through an interface .一个类可以通过一个interface公开它的任何公共方法。

The first thing to note is the common effect of extending B and implementing I .首先要注意的是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) . java 中的常见效果或明显结果是,您只能拥有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 .但是在您的情况下,您需要在I中的具体子类(在本例中为C foo()中实现和定义抽象方法foo()非常简单。

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 .所以Java认为class C中的这个method foo()是继承自interface I方法。 Otherwise you would have seen an error asking you to redefine the method foo() which is inherited from the interface.否则,您会看到一个错误,要求您重新定义从接口继承的method foo()

Unknowingly this also becomes a case of method overriding when you consider the superclass B .不知不觉中,当您考虑超类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 .由于Cfoo()方法具有与BI相同类型的声明(它应该根据标准、规则并满足实现接口的规则),因此它很容易满足接口以及覆盖B方法。

In your case, you are also overriding the method foo() in class B .在您的情况下,您还覆盖了B类中的方法foo()

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 .最后, class C只有一个foo()方法,它覆盖了B的方法,并且满足了implementing interface I的条件。

An example:一个例子:

Let the method foo() be defined (in C ) as:让方法foo()定义(在C )为:

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

Create 2 objects in C as follows:C创建 2 个对象,如下所示:

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

Call foo() :调用foo()

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

Ouput: Both prints Hello .输出:都打印Hello

Conclusion: foo() in C satisfies the interface (no error seen) and also overrides the method foo() in B .结论: C foo()满足接口(没有看到错误)并且还覆盖了B的方法foo()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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