黑马程序员——面向对象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”,轿车通过实现比赛接口拥有了比赛功能,扩展了它原有的功能。如果我们再定义别的接口,轿车类就又可以进一步扩展了。因此,接口内应定义扩展功能。

C语言-光伏MPPT算法:电导增量法扰动观察法+自动全局搜索Plecs最大功率跟踪算法仿真内容概要:本文档主要介绍了一种基于C语言实现的光伏最大功率点跟踪(MPPT)算法,结合电导增量法与扰动观察法,并引入自动全局搜索策略,利用Plecs仿真工具对算法进行建模与仿真验证。文档重点阐述了两种经典MPPT算法的原理、优缺点及其在不同光照和温度条件下的动态响应特性,同时提出一种改进的复合控制策略以提升系统在复杂环境下的跟踪精度与稳定性。通过仿真结果对比分析,验证了所提方法在快速性和准确性方面的优势,适用于光伏发电系统的高效能量转换控制。; 适合人群:具备一定C语言编程基础和电力电子知识背景,从事光伏系统开发、嵌入式控制或新能源技术研发的工程师及高校研究人员;工作年限1-3年的初级至中级研发人员尤为适合。; 使用场景及目标:①掌握电导增量法与扰动观察法在实际光伏系统中的实现机制与切换逻辑;②学习如何在Plecs中搭建MPPT控制系统仿真模型;③实现自动全局搜索以避免传统算法陷入局部峰值问题,提升复杂工况下的最大功率追踪效率;④为光伏逆变器或太阳能充电控制器的算法开发提供技术参考与实现范例。; 阅读建议:建议读者结合文中提供的C语言算法逻辑与Plecs仿真模型同步学习,重点关注算法判断条件、步长调节策略及仿真参数设置。在理解基本原理的基础上,可通过修改光照强度、温度变化曲线等外部扰动因素,进一步测试算法鲁棒性,并尝试将其移植到实际嵌入式平台进行实验验证。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值