多态思想
接口
1、接口描述
// 接口是一种约定规范,是多个抽象方法的集合。仅仅只是定义了应该有哪些功能,但本身不实现功能,至于每个功能具体怎么实现,就交给实现类完成。
// 接口中的方法是抽象方法,并不提供功能实现,体现了规范和实现相分离的思想,也体现了组件之间低耦合的思想。
// 所谓耦合度,就表示组件之间的依赖关系。依赖关系越多,综合性越强,同时表明组件的独立性越差,在开发中往往提出低耦合性,可提高其组件独立性。
// 接口也体现的是低耦合思想(接口同于模块间的解耦),接口仅仅提供方法的定义,却不提供方法的代码实现。那么得专门提供类并去实现接口,再覆盖接口中的方法,最后实现方法的功能。
2、接口定义和多继承性
接口可以认为是一种特殊的类,当时定义类的时候使用的是class关键字,而定义接口使用的是interface关键字。
接口定义语法:
public interface 接口名{
//抽象方法1();
//抽象方法2();
//抽象方法3();
}
接口表示具有某些功能的事物,接口名使用名词,一般以 I 开头。
接口中的方法都是公共的抽象方法
//接口具有多继承性
类可以继承类,但是只能单继承,接口也可以继承接口,但是却可以继承多个接口,也就是说一个接口可以同时继承多个接口。
接口与抽象类的区别:
接口多继承
抽象类单继承
3 、接口实现类
[1]因为接口中的方法是抽象的,没有方法体,所以接口不能创建对象。
[2]实现类可以继承父类,但可以同时实现一个或多个接口,继承在前,实现在后
[3]接口是一种引用数据类型,可以用来声明变量,并接收(引用)所有该接口的实现类对象
4、接口总结
//接口表示一种规约(规范、标准),它里面定义了一些列抽象方法(功能),它可以被多个类实现。
//实现类实现接口,必须实现接口中的所有抽象方法。我们经常说:接口约定了实现类应该具备的能力。
/**
* Person作为IWalkable的实现类,必须实现接口中所有的抽象方法
* ==> 接口约束实现类必须实现walk()方法
* ==> 实现类 has a 接口
* ==> 实现类具有接口中定义的功能
* ==> 接口约定了实现类应该具备的功能
*/
public class Person implements IWalkable,ISwimable{
@Override
public void walk() {
System.out.println("人类在步行...");
}
@Override
public void swim() {
System.out.println("人类在游泳...");
}
}
面向接口编程:
public class Test01 {
public static void main(String[] args) {
// 声明一个接口类型的变量
// 接口可以引用其所有的实现类对象
IWalkable walkable = null;
walkable = new Student();
walkable.walk();
walkable = new Frog();
walkable.walk();
/**
* 总结:当我们声明一个接口类型的变量时,它表示的意义是希望它的实现类应该具备什么功能,重心实现 * 类呀,你能不能满足接口约定的功能,
* 重心不在于持有数据,从未不依赖于任何某种特定类型的对象,进而对两个模块的功能进行解耦。
* ==> 接口在实际开发过程中用于两个模块/组件的解耦,降低耦合度。
* ==> 未来在架构师眼里,模块和模块之间的衔接都使用接口,架构师眼里只有接口,我们称为面向接口编 * 程。
*/
}
}
多态
1、多态概念
public class Test {
public static void main(String[] args) {
Animal animal = null;
animal = new Dog();
animal.shout();
animal.showInfo();
animal = new Cat();
animal.shout();
animal.showInfo();
/**
* 多态
* 同一引用类型的对象(animal),由于引用的子类实例不用(new Dog / new Cat),对同一行为(shout)产 * 生的结果不同,结果呈现多种形态/状态
* 这种情况在oop中称之为多态
*
* 多态发生的条件
* 1>必须继承
* 2>必须重写
* 3>多态建立在重写/实现的基础上
*
* 多态的实现形式
* [1]父类引用子类,子类必须重写父类的同名方法
*/
}
}
编译类型:声明对象变量的类型
运行类型:对象的真实类型
2、操作继承关系
//语法
父类 变量名 = new 实现类();
变量名.方法();
//父类引用变量指向于子类对象,调用方法时实际调用的是子类的方法。
3、操作实现关系
//语法
父类 变量名 = new 实现类();
变量名.方法();
接口引用变量指向实现类对象,调用方法时实际调用的是实现类实现接口的方法。
4、多态时方法调用问题
Animal a = new Cat();
a.shut();
//先判断shout方法是否在类类Animal类中:
找不到:编译报错
找 到:再看shout方法是否在子类Cat类中
找不到:运行父类方法
找 到:运行子类方法
多态中的类型转换
1、类型转换
//自动类型转换:把子类对象赋给父类变量
Animal a = new Dog();
Object obj = new Dog(); //Object是所有类的根类
//强制类型转换:把父类类型对象赋给子类类型变量
//语法:
子类类型 变量 = (子类类型)父类对象;
//在实际开发过程中,如果需要调用子类特有的方法时,一定要强制类型转换
Animal a = new Dog();
Dog d = (Dog) a; //正确
Cat c = (Cat) a; //错误
2、instanceOf
instanceOf 运算符:判断该对象是否是某一个类/接口的实例
//语法格式:
boolean b = 对象A instanceof 类B; //判断 A对象是否是 B类的实例?如果是,返回true
多态的好处–USB案例
需求:模拟在主板上安装鼠标、键盘等,比较没有规范和有规范的区别。
没有统一规范:
鼠标类:
public class Mouse {
//鼠标工作的方法
public void work1() {
System.out.println("鼠标在移动");
}
}
键盘类:
public class Keyboard {
//键盘工作的方法
public void work2() {
System.out.println("鼠标在移动");
}
}
主板类:
public class MotherBoard {
//在主板上安装鼠标对象
public void plugin(Mouse m) {
m.work1(); //调用鼠标工作的方法
}
//在主板上安装键盘对象
public void plugin(Keyboard k) {
k.work2(); //调用键盘工作的方法
}
}
上述的代码是没有统一规范的,问题:
1.不同设备中工作方法名称是不一致的
2.每次需要安装新设备,都需要在主板类上新增一个方法
有统一规范:
USB规范接口:
//定义一种规范,用来约束所有的USB设备应该具有的功能
public interface IUSB {
//USB设备工作的方法
void swapData();
}
鼠标类:
public class Mouse implements IUSB{
public void swapData() {
System.out.println("鼠标在移动");
}
}
键盘类:
public class Keyboard implements IUSB{
public void swapData() {
System.out.println("用键盘打字");
}
}
主板类:在安装方法plugin上体现出了多态的特征:
public class MotherBoard {
//IUSB类型可以接受实现类对象
public void plugin(IUSB usb) {
usb.swapData();
}
}
面向接口编程,体现的就是多态,其好处:把实现类对象赋给接口类型变量,屏蔽了不同实现类之间的实现差异,从而可以做到通用编程。
测试类:
public class USBDemo {
public static void main(String[] args) {
// 创建主板对象
MotherBoard board = new MotherBoard();
// 创建鼠标对象
Mouse m = new Mouse();
// 创建键盘对象
Keyboard k = new Keyboard();
//在主板上安装鼠标
board.plugin(m);
//在主板上安装键盘
board.plugin(k);
}
}
变量,屏蔽了不同实现类之间的实现差异,从而可以做到通用编程。**
测试类:
public class USBDemo {
public static void main(String[] args) {
// 创建主板对象
MotherBoard board = new MotherBoard();
// 创建鼠标对象
Mouse m = new Mouse();
// 创建键盘对象
Keyboard k = new Keyboard();
//在主板上安装鼠标
board.plugin(m);
//在主板上安装键盘
board.plugin(k);
}
}