JavaSE 19 Polymorphism 多态

第二十四章 Polymorphism 多态

extends继承或者implements实现,是多态的前提。
一个对象拥有多种形态,这就是对象的多态性。

  • 举例
    小明是一个学生,同时也是一个人
    小明是一个对象,
    小明对象即是学生形态,也有人类形态。

24.1 多态的格式与使用

代码当中体现多态性,其实就是一句话:父类应用指向子类对象。

  • 格式:
父类名称 对象名称 = new 子类名称();
or
接口名称 对象名称 = new 实现类名称();
public class Fu {
    
    
	
	public void method() {
    
    
		System.out.println("父类方法!")
	}
	
	public void methodFu() {
    
    
		System.out.println("父类特有方法!")
	}
	
}
public class Zi extends Fu {
    
    

	@Override
	public void method() {
    
    
		System.out.println("子类方法!")
	}
    
}
public class DemoMulti {
    
    
	
	public static void main(String[] args) {
    
    
		//使用多态的写法
		//左侧父类的引用,指向了右侧子类的对象
		Fu obj = new Zi();
		
		obj.method();//子类方法!
		obj.methodFu();
	}
    
}

24.2 多态中成员变量的使用特点

访问成员变量的两种方式:

  1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
  2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
    注意:成员变量不能覆盖重写,只有成员方法能重写。
public class Fu {
    
    
	
	int num = 10;
	
	public void showNum() {
    
    
		System.out.println(num);
	}
}
public class Zi extends Fu {
    
    
	
	@Override
	int num = 20;
	
	int age = 30;
	
	@Override
	public void showNum() {
    
    
		System.out.println(num);
	}
	
}
public class DemoMultiField {
    
    

	public static void main(String[] args) {
    
    
		//使用多态的写法,父类引用指向子类对象
		Fu ojb = new Zi();
		System.out.println(ojb.num);//父10
//		System.out.println(ojb.age);//错误写法
		System.out.println("==================");
		
		//子类没有覆盖重写,就是父10
		//子类如果覆盖重写,就是子20
		ojb.showNum();
	}
}

24.3 多态中成员方法的使用特点

在多态的代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。

  • 口诀: 编译看左边,运行看右边。
  • 成员变量:编译看左边,运行还看左边。
public class Fu {
    
    
	
	public void method() {
    
    
		System.out.println("父类方法");
	}
	
	public void methodFu() {
    
    
		System.out.println("父类特有方法");
	}
	
}
public class Zi extends Fu {
    
    
	
	@Override
	public void method() {
    
    
		System.out.println("子类方法");
	}
	
	public void methodZi() {
    
    
		System.out.println("子类特方法");
	}
	
}
public class DemoMultiMethod {
    
    
	
	public static void main(String[] args) {
    
    
		Fu obj = new Zi();
		
		obj.method();//优先用子
		obj.methodFu();//子类没有,父类有,向上查找到父
		//编译看左边,左边是Fu,Fu当中没有methodZi方法,所以编译报错。
//		obj.methodZi();//错误

	}
	
}

24.4 多态的好处

无论右边new的时候换成哪个子类对象,等号左边调用方法都不会变化。

  • 提高了代码的维护性(继承保证);提高了代码的扩展性

24.5 对象的向上转型

  • 定义:其实就是多态的写法
  • 格式:父类名称 对象名称 = new 子类名称();
  • 含义:右侧创建一个子类对象,把它当做父类看待使用。
  • 举例:
public abstract class Animal {
    
    
	public abstract void eat();
}
public class Cat extends Animal {
    
    
	@Override
	public void eat() {
    
    
		System.out.println("猫吃鱼");
	}
	
	public void catchMouse() {
    
    
		System.out.println("猫抓老鼠");
	}
}
public class Demo01Main {
    
    

	public static viod mian(String[] args) {
    
    
		Animal animal = new Cat();
		animal.eat();
	}
}
  • 注意事项:
  1. 向上转型一定是安全的,因为从小范围转向了大范围。
  2. 对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。

24.6 对象的向下转型

  • 定义:其实就是一个**【还原】**的动作
  • 格式:子类名称 对象名 = (子类名称) 父类对象;
  • 含义:将父类对象,【还原】成为本来的子类对象。
  • 举例:
public class Dog extends Animal {
    
    
	@Override
	public void eat() {
    
    
		System.out.println("狗吃骨头");
	}
	
	public void catchHouse() {
    
    
		System.out.println("狗吃看家");
	}
}
public class Demo02Main {
    
    

	public static viod mian(String[] args) {
    
    
		Animal animal = new Cat();
//		animal.catchMouse;//错误写法

		//向下转型
		Cat cat = (Cat) Animal;
		cat.catchMouse();
		
		//错误的向下转型
		//本来new的是一只猫,现在非要当成狗
//		Dog dog = (Dog) animal;	//可以编译,但是运行报错
	}
}
  • 注意事项:
    a.必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。
    b.如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。
    java.lang.ClassCastException 类转换异常

其实类似于:基本类型中的强制类型转换

int num1 = (int) 10.0;
int num2 = (int) 10.5;	//不可以,精度损失。

24.7 instanceof 关键字进行类型判断

如何才能知道一个父类引用对象,本来是什么子类?
格式:

对象 instanceof 类名称
//这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。
//参考24.5-24.6
public class DemoInstanceof {
    
    

	public static void main(String[] args) {
    
    
		Animal animal = new Dog();
				
		giveMeAPat(new Dog());
	}

	public static void giveMeAPat(Animal animal) {
    
    
		if (animal instanceof Dog) {
    
    
			Dog dog = (Dog) animal;
			dog.watchHouse();
		}
		
		if (animal instanceof Cat) {
    
    
			Cat cat = (Cat) animal;
			Cat.catchMouse();
		}		
	}

}

24.8 笔记本USB 接口案例

public abstract class USB {
    
    
	
	public abstract void open();
	
	public abstract void close();
	
}
public class Computer {
    
    
	public void powerOn() {
    
    
		System.out.println("开机");
	}
	
	public void powerOff() {
    
    
		System.out.println("关机");
	}
	
	//使用USB设备的方法,使用接口作为方法的参数
	public void useDevice(USB usb) {
    
    
		
		usb.open;
		if (usb instanceof Mouse) {
    
    
			Mouse mouse = (Mouse) usb;
		} else if (usb instanceof Keyboard) {
    
    
			Keyboard keyborad = (Keyboard) usb;
		}
		usb.close;
	}
}
public class Mouse implement USB {
    
    
	
	@Override
	public void open() {
    
    
		System.out.println("打开鼠标");
	}
	
	@Override
	public void close(){
    
    
		System.out.println("关闭鼠标");
	}
	
	public void press(){
    
    
		System.out.println("点击鼠标");
	}
}
public class Keyboard implement USB {
    
    
	
	@Override
	public void open() {
    
    
		System.out.println("打开键盘");
	}
	
	@Override
	public void close(){
    
    
		System.out.println("关闭键盘");
	}
	
	public void type(){
    
    
		System.out.println("输入文字");
	}
}
public class DemoMain {
    
    
	public static void main(String[] args) {
    
    
		Computer computer = new Computer();
		computer.poweron();

		USB usbMouse = new Mouse();//多态写法
		computer.useDevice(usbMouse)
		
		Keyboard keyboard = new Keyboard();//没有使用多态写法
		computer.useDevice(Keyboard);//发生了向上转型
//		computer.useDevice(new Keyboard());//同上
		computer.poweroff();
	}
}

猜你喜欢

转载自blog.csdn.net/Niiuu/article/details/104232921
今日推荐