多态和抽象类

1.多态

生活中的多态:同一个动作,因为环境的不同,产生不一样的效果
程序中的多态:同一段代码,因为实参的不同,产生不一样的效果
多态的实现方式:
1.父类作为形参,实参为子类类型
2.父类作为返回值,实际返回值类型为子类

package com.qfedu.test1;
/**
 * 	父类:宠物类
 * @author WHD
 *
 */
public class Pet {
	private String name;
	private int health;
	private int love;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHealth() {
		return health;
	}
	public void setHealth(int health) {
		this.health = health;
	}
	public int getLove() {
		return love;
	}
	public void setLove(int love) {
		this.love = love;
	}
	
	
	public void print() {
		System.out.println("宠物的名字是" + name + ",健康值是" + health + ",爱心值是" + love);
	}
	
	public void toHospital() {
		System.out.println("宠物看病");
	}
	@Override
	public String toString() {
		return "name=" + name + ", health=" + health + ", love=" + love + "]";
	}
	
}
package com.qfedu.test1;
/**
 * 	狗类
 * 		名字
 * 		健康值
 * 		爱心值
 * 		品种
 * 	打印狗狗信息
 * @author WHD
 *
 */
public class Dog extends Pet{
	private String strain;
	
	public String getStrain() {
		return strain;
	}
	public void setStrain(String strain) {
		this.strain = strain;
	}
	
	public Dog() {}
	
	public void toHospital() {
		System.out.println("狗狗看病,吃药,吃骨头,健康值恢复了");
		this.setHealth(100);
	}
	@Override
	public String toString() {
		String str = super.toString();
		return "Dog [strain=" + strain  + ","+ str;
	}
	
}
package com.qfedu.test1;
/**
 * 	企鹅类
 * 		名字
 * 		健康值
 * 		爱心值
 * 		性别
 * 	打印信息
 * @author WHD
 *
 */
public class Penguin extends Pet{
	private String sex;
	
	public String getSex() {
		return sex;
	}
	
	public void setSex(String sex) {
		this.sex = sex;
	}
	
	public Penguin() {}
	
	public void toHospital() {
		System.out.println("企鹅看病,打针,疗养,吃鱼,健康值恢复了");
		this.setHealth(100);
	}
	
}
package com.qfedu.test1;
/**
 * 	需求:
 * 	1.在原来宠物系统的基础上,添加给宠物看病的功能
 * 	2.添加开业抽奖送宠物的活动
 * @author WHD
 */
public class Test {
	public static void main(String[] args) {
		Master zhaosi = new Master();
		Dog dog = zhaosi.giveDog();
		System.out.println(dog);
		
		Penguin p = zhaosi.givePenguin();
		System.out.println(p.getName());
		System.out.println(p.getHealth());
		System.out.println(p.getLove());
		System.out.println(p.getSex());
		System.out.println("========================================");
		// 父类引用 指向子类对象
		// 多态 向上转型 此时可以调用子类重写父类的方法 和 父类访问权限允许的方法
		// 不能调用子类独有的方法 如果需要调用则需要向下转型 
		Pet pet1 =  zhaosi.give("一等奖");
		System.out.println(pet1.getName());
		System.out.println(pet1.getHealth());
		System.out.println(pet1.getLove());
		Penguin p1 = (Penguin)pet1;
		System.out.println(p1.getSex());
		System.out.println("==========================================");
		Pet pet2 = new Penguin();
		int a = 20;
		double b = a;
	}
}

2.向上、向下转型

1.向上转型:Pet pet = new Dog();
此时可以调用子类重写父类的方法和继承父类的方法,不能访问子类独有的方法
2.向下转型:Dog dog = (Dog)pet;
向下转型是指将指向子类对象的父类引用转换为子类类型而不是直接将一个父类类型强制转换为子类,此时可以调用子类独有的方法以及继承父类、重写父类的方法。

package com.qfedu.test2;

import com.qfedu.test1.Dog;
import com.qfedu.test1.Penguin;
import com.qfedu.test1.Pet;

public class TestPet {
	public static void main(String[] args) {
		// ctrl + shift + o 导入本类中所需要的所有包
		Pet pet = new Dog(); 
		pet.setHealth(100);
		pet.setLove(100);
		pet.setName("大黄");
		Dog dog = (Dog) pet;
		dog.setStrain("金毛");
		
		
		Pet pet1 = new Pet();
		// 在实际类型转换的过程中 我们会使用instanceof关键字判断类型是否可以正确转换
		// 对象名 instanceof 类名 表示判断左侧的对象是否属于右侧的类型 返回值为布尔类型的
		if(pet1 instanceof Penguin) {
			Penguin p1 = (Penguin) pet1; // 这种将报类型转换异常 ClassCastException
		}else {
			System.out.println("类型不匹配");
		}
		System.out.println("程序结束");
	}
}

3.instanceof关键字

对象名 instanceof 类名
表示判断左侧的对象是否属于右侧的类型,返回值为布尔类型的

package com.qfedu.test3;

import com.qfedu.test1.Dog;

public class Person {
	private String name;
	private String idCard;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIdCard() {
		return idCard;
	}
	public void setIdCard(String idCard) {
		this.idCard = idCard;
	}
	
	
	public Person() {
	}
	
	public Person(String name, String idCard) {
		this.name = name;
		this.idCard = idCard;
	}
	public boolean equals(Object obj) {
		if(this == obj) {
			return true;
		}
		if(obj instanceof Person) {
			Person p1 = (Person) obj;
			if(this.getName().equals(p1.getName()) && this.getIdCard().equals(p1.getIdCard())) {
				return true;
			}
		}
		return false;
	}
	public static void main(String[] args) {
		Person p1 = new Person("赵四", "12457332597891232321");
		Person p2 = new Person("赵四", "12457332597891232321");
		Dog dog = new Dog();
		dog.setName("大黄");
		dog.setHealth(100);
		dog.setLove(100);
		dog.setStrain("金毛");
		
		System.out.println(p1.equals(dog));
		System.out.println(p1.equals(p2));
	}
}

4.抽象类

1.抽象方法没有方法体,必须存在于抽象类中,抽象方法和抽象类都必须使用abstract修饰
2.抽象类不能直接new对象,必须通过new子类对象的方式创建多态向上转型
3.子类必须重写父类的抽象方法,除非子类也是抽象类
4.抽象类中可以书写普通方法、普通属性和构造方法
5.可以书写静态方法,静态方法可以被继承,不能被重写
6.抽象类实现多态与之前一致

package com.qfedu.test5;
/**
 * 	门类
 * 	因为门的具体的类别不确定 所以门的行为无法具体描述
 * 	但是 只要是门 都能开和关
 * @author WHD
 *
 */
public abstract class Door {
	public abstract void open();
	
	public abstract void close();
}
package com.qfedu.test5;

public class CommonDoor extends Door{

	@Override
	public void open() {
		System.out.println("普通门开门,插入钥匙,轻轻一转,门开了,吱~");
	}
	@Override
	public void close() {
		System.out.println("普通门关门,咣当一声,手动关门");
	}
}
package com.qfedu.test5;

public class SecurityDoor extends Door{

	@Override
	public void open() {
		System.out.println("防盗门开门,插入钥匙,输入密码,指纹+视网膜识别,门开了");
	}

	@Override
	public void close() {
		System.out.println("防盗门关门,红外线扫描障碍,自动关闭");
	}
}
package com.qfedu.test5;

public class Person {
	
	public void openDoor(Door door) {
		door.open();
	}
	
	public void closeDoor(Door door) {
		door.close();
	}
	
	
	public Door buyDoor(double money) {
		if(money > 2000) {
			return new SecurityDoor();
		}else {
			return new CommonDoor();
		}
	}
	public static void main(String[] args) {
		Person p1 = new Person();
		Door door1 = new CommonDoor();
		p1.openDoor(door1);
		Door door2 = new SecurityDoor();
		p1.openDoor(door2);
		
		p1.closeDoor(door1);
		p1.closeDoor(door2);

	}
}
posted @ 2021-07-24 14:37  码丁XIA  阅读(90)  评论(0)    收藏  举报