Java中“接口”与“类”的关系

类与类

继承关系,只能单继承,可以多层继承。

接口和接口之间的关系

继承关系,可以单继承,也可以多继承,并且可以多层继承。
注意:
1.如果多个父接口中有同名的抽象方法,那么子接口只需要实现一次即可
2.如果多个父接口中有同名的默认方法,那么子接口必须重写默认方法,必须要加default关键字
3.如果多个父接口中有同名的静态方法,那么无须理会,因为静态方法只能供接口使用
4.如果多个父接口中有同名的私有方法,那么无须理会,因为私有方法只能本接口使用

接口和类之间的关系

实现关系
单实现: 一个类只实现一个接口
多实现: 一个类可以同时实现多个接口并且还可以在继承一个类的同时实现多个接口。
格式:
public class 类名 implements 接口名1,接口名2,…{ }
格式:
public class 类名 extends 父类名 implements 接口名1,接口名2,…{ }

注意:
1.如果多个接口中有同名的抽象方法,那么实现类只需要实现一次即可
2.如果多个接口中有同名的默认方法,那么实现类必须重写一次,并且要去掉default关键字
3.如果多个接口中有同名的静态方法,那么实现类无须理会,接口中的静态方法只供接口直接使用
4.如果多个接口中有同名的私有方法,那么实现类无须理会,因为接口中的私有方法只能在本接口中使用

子接口重写父接口的默认方法,必须加default关键字
实现类重写接口中的默认方法,必须去掉default关键字

注意:
1.如果接口父类中有同名默认方法,优先调用父类的默认方法(后文有详述)
2.如果接口父类中有同名抽象方法,那么子类必须重写一次抽象方法

普通类、抽象类和接口

普通类: 成员变量,构造方法,成员方法,静态代码块
抽象类: 成员变量,构造方法,成员方法,静态代码块,抽象方法 —> 不能直接创建对象
接口: 常量,默认方法,静态方法,私有方法,抽象方法 —> 不能直接创建对象

接口->抽象类->普通类:
接口是抽象类中的抽象类,他们是存在宗族关系的,接口是爷爷辈,抽象类是父辈,普通类是子孙辈

接口作为方法的参数,可以接收该接口的所有实现类的对象
接口作为方法的返回值,可以返回该接口的所有实现类的对象

抽象类(abstract class):
a.抽象类是仅供派生的类,无法实例化一个抽象类,只能实例化从它派生的类。
b.抽象类的主要特征在于它包含抽象成员(abstract member),抽象成员是不具有实现的一个方法或属性,其作用是强制所有派生类提供实现。
c.由于抽象成员应当是要被重写(override)的,因此这类成员会自动成为virtual成员,而且不能显示地声明。
d.抽象成员不能是private的,否则派生类看不见他们。

接口(interface):
a.接口是抽象类的变体。
b.接口的一个关键特征是它既不包含实现,也不包含数据(这里先暂时简单理解,其实是可以有默认方法和常量的,后文有所提及)。
c.字段(也就是数据)不能出现在一个接口中,如果一个接口要求派生类包含特定的数据,那么它会使用属性而不是字段。由于属性不会包含任何实现作为接口声明的一部分,所以他不会引用一个支持字段。
d.接口的宗旨是定义由多个类共同遵守的一个契约,所以接口中所有成员都必须为public类型。抽象类可以不用实现接口的全部方法。

抽象类和接口的区别
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的;而类是可以有私有方法或私有变量的,另外,实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。接口所有方法都是抽象的,即接口里只能有抽象方法;抽象类里面可以有非抽象的方法,但抽象类至少要有一个抽象方法。接口的成员变量都是public static final,抽象类没有这个限制。接口里只有终极变量和抽象方法,它是其他类实现它的一个标准,实现接口要具体化接口里的所有抽象方法。类的成员变量是类变量和方法(它们没有什么特殊要求)。

抽象类中的抽象方法声明时不能有大括号,而接口中的所有方法都没有大括号。

有的时候需要将接口和抽象类配合起来使用,这样可以为开发者提供相当的便利性,开发者觉得哪个方便就选用哪个。这样的抽象类称为便利类。此时,便利类并不需要实现接口的所有方法,可以留给继承它的子类去实现它们。

这么做并非是没有意义的,当你自己写的类想用接口中个别方法的时候(注意不是所有的方法),那么你就可以用一个抽象类先实现这个接口(暂时不用的方法的方法体中为空,后面用到时再重写覆盖),然后再用你的类继承这个抽象类,这样就可以达到你的目的了,如果你直接用类实现接口,那是所有方法都必须实现的。

那么为什么会引入接口这个东西呢?

之所以有接口的产生,是源于技术的瓶颈(或产生了矛盾)——为了解决菱形继承问题
在这里插入图片描述
在这里插入图片描述

最好的办法就是使用多重继承
在这里插入图片描述
新建一个宠物类,让猫和狗都去继承宠物类的属性和方法。但是这样就会导致一个问题。即菱形继承问题。
在这里插入图片描述
如果宠物类和动物类都有eat方法,作为一个猫类要想继承两个父类的话,到底是继承哪一种eat方法呢。这样的问题就称之为菱形问题。事实上,Java为了避免这样的问题,是不允许多重继承的。但是,如果你又想实现多重继承怎么办呢?毕竟多重继承也有好处。那么,就可以使用接口来去实现。

接口

接口解决菱形继承的办法是通过将全部的方法设为抽象,如此一来,子类要想继承就必须去实现这个方法。

接口定义一般这么写:
public interface Pet
{
public abstract void play();
}

接口实现要这么写:
public class Dog extends Canine implements Pet{ }

接下来具体举一个例子来展示接口如何解决菱形继承问题:
在这里插入图片描述
在这里插入图片描述
我们把接口的方法实现注释掉,Test就会继承Parent的方法。反之,如果不注释的话,就实现接口中定义的方法。只要父类中存在接口中的方法,只要没必要改动,就可以不用override了,即执行父类方法。如果override,则执行接口中的方法,即接口重写的方法会覆盖父类的方法。若在接口中调用父类方法,则两者都会执行。解决了菱形继承不知道继承哪一个的问题。

Java中的类为什么只能单继承

Java中能创建对象的具体类就证明该具体类中的方法已经全部实现,如果两个具体类具有相同方法(但不同实现) ,而某个对象同时由这两个具有相同方法(但不同实现)的具体类所创建,则当对象调用相同的方法时,就不知道调用哪个方法。因此导致菱形继承问题。

Java中允许接口多继承

接口中的方法都自动默认为public和abstract的 ,只有实现方法(同一方法正常情况下只实现一次)后才能创建对象,所以不会引起方法冲突问题。

如果一个类的父类和接口都有同一个方法

那子类的到底调用的是父类的、还是接口的方法?

先说结论为敬:不Override重写接口时父类优先;Override重写接口时接口优先。

解决默认方法冲突(注意注意注意默认方法!!!)
默认方法是在接口中实现的方法。

在这里插入图片描述
在这里插入图片描述
所以,不Override重写接口时父类优先;Override重写接口时接口优先。总之,接口既解决了菱形继承问题,同时也保证只能继承一个方法。

参考:
https://www.cnblogs.com/libinhong/p/10990476.html
https://blog.csdn.net/Einstellung/article/details/106650692
《Head First Java 2nd Edition》、《Java核心技术卷Ⅰ》

如果大家喜欢这篇文章的话,希望大家收藏、转发、关注,转载请注明出自这里。 PS:本随笔属个人学习小结,文中内容有参考互联网上的相关文章。如果您博文的链接被我引用,我承诺不会参杂经济利益。其中如果发现文中有不正确的认知或遗漏的地方请评论告知,谢谢! 还是那句话:不是我喜欢copy,是站在巨人的肩膀上~

猜你喜欢

转载自blog.csdn.net/Mrsgflmx/article/details/107733568
今日推荐