- 概念
面向对象编程有三大特性:封装、继承、多态。
1.封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。
2.继承是为了重用父类代码。两个类若存在IS-A的关系就可以使用继承。
3.多态指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
-
格式
基于继承实现的多态:父类类型名 变量名 = new 子类()
基于接口实现的多态:接口类型 变量名 = new 实现类() -
简单示例
public class Parent {
int age;//年龄
public void eat() {
System.out.println("父母正在吃饭");
}
public void sleep() {
System.out.println("父母正在睡觉");
}
}
public class Child extends Parent {
int id = 10;//学号
public void eat() {
System.out.println("孩子正在吃饭");
}
public void study() {
System.out.println("孩子正在上学");
}
}
public class show {
public static void main(String[] args) {
//继承
Child C1 = new Child();
C1.sleep();//子类继承了父类的方法,可以调用此方法
System.out.println(C1.id);//继承
//向上转型
Parent P = new Child();
P.eat();//子类重写了父类方法,可以调用此方法
//P.study();编译无法通过
//System.out.println(P.id);//编译无法通过
//向下转型
Child C2 = (Child)P;
C2.sleep();
C2.study();//向下转型为子类,可以调用此方法
}
}
console结果:
父母正在睡觉
10
孩子正在吃饭
父母正在睡觉
孩子正在上学
向上转型优点:实现了多态;
向上转型不足:只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,无法访问;
向下转型优点:增加灵活;
向下转型不足: 编写时出现类型转换错误,编译时不会提示,运行后才会报错;
Tip:boolean B = 类 类型变量 instanceof 类名
- 总结
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
- 接口的多态实现
使用前:
//接口
public interface UsbInter {
public abstract void Load();//加载
public abstract void Use();//操作使用
public abstract void Close();//关闭
}
//鼠标
public class Mouse implements UsbInter {
public void Load() {
System.out.println("鼠标驱动加载中");
}
public void Use() {
System.out.println("鼠标操作中");
}
public void Close() {
System.out.println("鼠标停止使用");
}
}
//屏幕
public class Screen implements UsbInter{
public void Load() {
System.out.println("屏幕驱动加载中");
}
public void Use() {
System.out.println("屏幕操作中");
}
public void Close() {
System.out.println("屏幕停止使用");
}
}
//主机
public class Computer {
public void Run(Mouse m) {
m.Load();
m.Use();
m.Close();
}
public void Run(Screen s) {
s.Load();
s.Use();
s.Close();
}
}
//实现函数
public class Show {
public static void main(String[] args) {
Mouse Logitech = new Mouse();
Screen LG = new Screen();
Computer PC = new Computer();
PC.Run(Logitech);
PC.Run(LG);
}
}
console结果:
鼠标驱动加载中
鼠标操作中
鼠标停止使用
屏幕驱动加载中
屏幕操作中
屏幕停止使用
总结:每添加一个usb设备就要在Computer类中增加此设备的运行方法,如果设备多的话工作量大;
使用后:
第一种写法:
//主机
public class Computer {
UsbInter usb;
public void Run() {
usb.Load();
usb.Use();
usb.Close();
}
}
//实现
public class Show {
public static void main(String[] args) {
Mouse Logitech = new Mouse();
Screen LG = new Screen();
Computer PC = new Computer();
PC.usb = LG;//UsbInter usb = new Screen();
PC.Run();
PC.usb = Logitech;//UsbInter usb = new Mouse();
PC.Run();
}
}
第二种写法:仅将computer类按如下重新编写,其他不变,运行结果相同
public class Computer {
public void Run(UsbInter usb) {
// UsbInter usb = new Mouse();
// UsbInter usb = new Screen();
usb.Load();
usb.Use();
usb.Close();
}
}
//实现
public class Show {
public static void main(String[] args) {
Mouse Logitech = new Mouse();
Screen LG = new Screen();
Computer PC = new Computer();
PC.Run(Logitech);
PC.Run(LG);
}
}
分析:usb设备执行Run方法,执行了UsbInter usb = new 设备类();
总结:每添加一个usb设备只需要在实现函数中,创建对象再调用即可,这就是多态的灵活性,复用性,扩展性;