黑马程序员——面向对象14:接口

本文详细介绍了接口的概念、书写方式、用法以及多实现、多继承的特点,并通过实例展示了接口如何提高代码的扩展性和降低耦合性,进而解释了接口在编程中的核心价值。

------- android培训java培训、期待与您交流! ----------

1. 接口的书写格式

我们可以把接口理解为一种特殊的抽象类,因为接口特点之一就是它所有的方法都是抽象的。接口的书写格式如下:

代码1:

interface Inter
{
	//常量
	public static final doublePI = 3.14;
	//抽象方法
	public abstract void f();
}
接口的标识符是interface,这与类的标识符class是有区别的。通常,在接口内部定义的都是常量和抽象方法,并且两者修饰符都是固定的,常量的修饰符:public static final;方法的修饰符:public abstract。大家需要注意的是:只要定义的是接口,那么其内部的常量和方法的上述修饰符不必手动添加,系统会自动添加缺少的修饰符。但是为了提高代码的阅读性,应尽量将修饰符添加齐全。

2. 接口的用法

接口和抽象类一样,因为抽象方法的存在,无法创建实例对象,也要通过子类“继承”的形式复写方法。对于接口来说,它的子类和接口之间的关系不再称为“继承”,而是称为“实现”,关键字为“implements”。以上述Inter接口为例,

代码2:

interface Inter
{
	//常量
	public static final doublePI = 3.14;
	//抽象方法
	public abstract void f();
}
class Demo implements Inter
{
	public void f()
	{
		System.out.println(“Demo run”);
	}
}
class InterfaceDemo
{
	public static voidmain(String[] args)
	{
		Demo d =new Demo();
		System.out.println(d.PI);
		System.out.println(Demo.PI);
		System.out.println(Inter.PI);
	}
}
运行结果为:

3.14

3.14

3.14

这表明,虽然不能调用接口的方法,但是可以通过接口名调用接口内的常量。当然,由于final修饰符的原因,无论是通过接口名、类名还是对象调用该常量,都是不能重新赋值的。此外,上述代码中子类Demo实现了Inter接口,并复写了f()方法。

3. 继承与实现的区别

从形式上看,好像子类实现接口和子类继承抽象父类没有什么区别。实际上,抽象父类中既有抽象方法还有非抽象方法,子类继承了非抽象方法,就可以直接使用了,也就是说子类还是从父类“继承”了一些现成的东西,不必完全由自己定义;而对于接口来说,子类只有把接口的所有方法全部复写一遍,也就说是将这些抽象方法“实现”为真正的有实际用途的方法以后,才能使用。

4. 接口的多实现

所谓多实现,就是一个类可以实现多个接口。多实现的格式如下:

代码3:

interface Inter1
{
	public abstract void f_1();
}
interface Inter2
{
	public abstract void f_2();
}
class Demo2 implements Inter1, Inter2
{
	public void f_1()
	{
		System.out.println(“f_1run”);
}
	public void f_2()
	{
		System.out.println(“f_2run”);
	}
}
子类通过逗号分隔实现的多个接口,并复写所有接口的所有非同名抽象方法。这里为什么要强调非同名方法,因为假如两个接口定义了两个同名的抽象方法(两个方法的返回值类型必须相同,否则会出现编译错误),子类实现了这两个接口以后,实际上只需要复写一次该方法就行了,这就是接口可以实现多实现的原因,因为接口的方法没有方法体,在都只有方法名的情况下不存在子类无法区分两个方法的问题。而继承体系中,如果两个父类定义了两个同名方法,那么子类在继承并调用的时候,就会出现问题。

此外,子类在继承了某个类的情况下还可以进行多实现,比如,

代码4:

class Sub extends Super implements Inter1, Interface2{}

小知识点1:

类与类之间是继承;

接口与类之间是实现;

接口与接口之间只能是继承,这是因为,所谓实现,必须由子类将接口的抽象方法复写,并定义具体的实际内容,而接口内部都是抽象方法,也就不可能具体实现了。


5. 接口的多继承

前面的内容中我们讲到,Java中不允许直接地多继承,而是通过其他的方法间接实现,那就是通过接口来多继承

代码5:

interface Inter1
{
	public abstract void f_1();
}
interface Inter2
{
	public abstract void f_2();
}
interface Inter3 extends Inter1, Inter2
{
	public abstract void f_3();
}
接口可以实现多继承的原因和它允许多实现的原因是一样的,就是因为接口的方法没有方法体,即使方法名相同也不会造成混乱。但是,不能出现方法名相同,而返回值类型不同的情况,比如:

代码5:

interface Inter1
{
	public abstract int f();
}
interface Inter2
{
	public abstract booleanf();
}
interface Inter3 extends Inter1, Inter2{}
对于上述代码,如果有子类实现了Inter3接口,那么复写了两个f()方法以后,就会出现返回值类型混乱的情况,当调用子类对象的f()方法时无法确定返回值类型到底是什么。那么这就是Java中唯一可以实现多继承的地方,除此以外,均不能进行多继承。

6. 接口的意义

为了大家更好的理解接口的存在意义,我们举一个现实生活中的例子来说明。早期的CPU都是焊死在主板上的,然而CPU的更新换代速度以及人们对CPU处理性能的要求越来越高,将CPU焊死在主板上的方式显然不能满足人们的要求——每次需要升级电脑都要重新购买新的设备。

这个时候,为了提高计算机的扩展性,人们在主板上专门设计了一个通用的CPU插槽,有了这个插槽,就可以方便的更换符合这类插槽“规则”的CPU而不需要重新购买电脑了。有了这种“插槽”的设计,就降低了CPU和主板的耦合性,换句话说,原来CPU和主板之间的关系非常紧密,而现在二者关系的紧密程度大大降低,也就是解耦了。此外,不仅可以设计CPU的插槽,还可以设计显卡插槽、声卡插槽、网卡插槽等等,只要板卡符合对应C插槽的规则就可以使用,大大提高了计算机功能的扩展性,这就是“插槽”的好处。而这里“插槽”就可以理解为程序中的“接口”,同样提高了代码的扩展性。

那么降低了耦合性以后,无论对厂商还是对消费者都是有好处的。对厂商来说,CPU厂商和主板厂商就可以专门研发各自的产品,而不需要分散精力;对于消费者来说,方便的更换自己需要的板卡,随意进行功能扩展。

我们用一段代码来说明接口的意义,比如我们定义车辆(Vehicle)类,车辆类中有一个开车方法(定义了具体的方法体)和加油的抽象方法(因为不同的车加不同的油)。再定义一个轿车(Sedan)类继承车辆类,复写加油方法,并打印“加93号汽油”。我们又希望这个轿车通过改装变成赛车,也就说为它增加一个比赛功能,此时我们为了增加代码的扩展性,定义一个比赛接口,其内部定义一个比赛方法,轿车类实现比赛接口并复写比赛方法即可。

代码6:

/*
	定义抽象类——车辆。
	由于不同车加不同的油,加油方法定义为抽象方法
*/
abstract class Vehicle
{
	//抽象方法,加油
	abstract void refuel();
	//开车方法
	public void drive()
	{
		System.out.println("开车");
	}
}
/*
	比赛接口,实现该接口,可获得比赛功能
*/
interface Racing
{
	public abstract voidrace();
}
/*
	轿车类继承车辆类,复写加油方法;
	实现比赛接口,复写比赛方法
*/
class Sedan extends Vehicle implements Racing
{
	public void refuel()
	{
		System.out.println("加93号汽油");
	}
	public void race()
	{
		System.out.println("进行赛车比赛");
	}
}
class InterfaceTest
{
	public static voidmain(String[] args)
	{
		Sedan s = newSedan();
		s.refuel();
		s.drive();
		s.race();
	}
}
运行结果为:

加93号汽油

开车

进行赛车比赛

通过这样的设计,可以让有需要的轿车类,通过实现比赛接口,而拥有比赛功能;反之,如果将比赛功能定义在车辆类中,只要继承了车辆类就会拥有比赛功能,而这是不符合现实情况的。

通过上述例子,我们可以进一步理解实现和继承的区别:继承的关系可以理解为“is a”,轿车是车辆的一种,通过继承子类应该拥有该继承体系的基本方法;实现的关系可以理解为“like a”,轿车通过实现比赛接口拥有了比赛功能,扩展了它原有的功能。如果我们再定义别的接口,轿车类就又可以进一步扩展了。因此,接口内应定义扩展功能。

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值