当派生类扩展基类并同时实现接口时,谁的方法被重写?



情况 1:

我有一个接口.java:

interface Inter
{
void abcd();
}

基类:

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

派生类:

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();
}
}

现在我编译它:

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$ 

这意味着类 Use 中被覆盖的方法 abcd() 来自实现的接口 "Inter",而不是来自基类 "Base"。

案例2:

我们有一个文件测试.java包含以下代码:

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");
}
}

当我们执行它时,我们得到:

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

由于 t.start() 执行了方法 run(),这意味着类 Thread 的方法 run() 被覆盖了。但是在这种情况下,接口"Inter"的1方法abcd()被覆盖了。

在情况 1 中:在类 Use 中覆盖了谁的方法 abcd()?类基础还是接口间?错误说我们正在覆盖接口 Inter 的 abcd()。但在情况 2 中:我们似乎没有覆盖接口 Ab 的方法运行。因为我们可以通过调用 t.start() 来执行 run() 方法。这只有在我们覆盖类 Thread 的 run() 时才有可能。

类中的方法重写基类方法并同时实现接口。

重写方法与实现接口不完全相同:

  • 重写超类中的方法意味着要替换其实现。如果未提供重写方法,则将使用超类(可以为空)的实现。
  • 实现
  • 接口方法时,您将为简单声明(没有任何实现)提供代码。如果将非抽象类声明为实现接口,但不为接口的每个方法提供实现,则编译将失败。在 Java 8 中则不然,您可以选择在接口中提供默认实现,但在这种情况下,来自超类的任何实现都将获胜。

方法的实现和重写始终可以扩展其可见性,但不能降低其可见性。这意味着:

  • 超类中的包私有(默认可见性)或受保护方法可以在子类中公开
  • 但是,超类中的公共方法不能在子类中成为包私有或受保护。

接口中的方法始终是公共的,即使接口中未指定"public"修饰符也是如此。因此,它们的实现也必须是公开的=>这是您在案例1中遇到的错误

作为旁注,在您的情况 2 中,您使用了错误的线程。不要子类线程。相反,创建一个实现 Runnable 或 Callable 接口的类,并将其提交到线程池(请参阅 java.util.concurrent 中的类,或者使用 java 8 的ForkJoinPool.commonPool().submit(myTask)进行快速测试。

两者兼而有之。方法重写取决于方法的名称和签名,而不是定义方法的位置。如果在多个祖先上定义,它将覆盖这两个祖先。 注意:如果在一个中定义为公开,而在另一个中定义为受保护,则该属性将变为公开。

Inter接口中,void abcd();是抽象方法的定义。所有抽象方法本质上都是公共的。

从{定义接口},

接口中的所有抽象方法、默认方法和静态方法都是隐式公共的,因此您可以省略 public 修饰符。

所以,虽然Interabcd()public,但Use的实际实现是说abcd()的实现是package-private,这是一种较弱的访问权限。这应该解决您的评论"//intentionally not using public"
传统上,abcd()也应该使用注释@Override(尽管这不是硬性要求)。

在第二个示例中,Thread类提供了run()的具体实现。鉴于A#run()是公共的,您已经满足接口Ab对访问说明符的要求。然后,A#run()继续覆盖Thread#run()- 这正是我们期望继承的行为方式。

总而言之,我们刚刚看到了extends(扩展或覆盖类方法)和implements(给定类为接口中的所有方法状态提供实现的合约)之间的区别。{这个答案}对此进行了更深入的介绍,并且是一本很好的读物。

如果这个答案的任何部分需要更清楚,请告诉我。

最新更新