多态概念、特点及使用场景

一 : 多态

1.1 什么是多态

多态: 把子类对象伪装成父类类型

  • 让父类类型指向子类对象
  • 给子类对象起一个父类类型的名字
  • 父类类型的引用=子类类型的对象

1.2 多态对象有那些特点

多态对象: 起了父类类型名字的子类对象

  • 特点1:多态对象不能访问子类特有成员
  • 特点2:多态对象被重新定义的属性表现的是父类中的数据
  • 特点3:多态对象被重写的方法表现的是子类中定义的方法
  • 总而言之:多态对象除了重写的方法 其他和父类对象完全相同

1.3 什么时候使用多态

情况1

cat类 dog类

  • 饲养员类: wei方法:给狗、猫喂食物、运动起来来
  • 不使用多态
public static void main(String[] args) {
		Dog1 d1=new Dog1("哈趴狗");
		Cat1 c1=new Cat1("波斯猫");
		Demo02DuoTaiUse1  syy=new Demo02DuoTaiUse1();
		syy.wei(c1);
        syy.wei(d1);
    }
	//方法可以使用的数据:成员变量+参数列表
	private void wei(Dog1 d) {//此方法只能实现喂狗
		d.eat();
		d.yunDong();
	}
	private void wei(Cat1 d) {//此方法只能实现喂猫
		d.eat();
		d.yunDong();
	}
}
class Dog1{
	String name;
	public Dog1(String name) {
		this.name=name;
	}
	void eat() {
		System.out.println("狗:"+name+"正在吃骨头!");
	}
	void yunDong() {
		System.out.println("狗"+name+"看门!");
	}
}
class Cat1{
	String name;
	public Cat1(String name) {
		this.name=name;
	}
	void eat() {
		System.out.println("猫:"+name+"正在吃鱼!");
	}
	void yunDong() {
		System.out.println("猫"+name+"晒太阳!");
	}
  • 不使用多态实现:

    • 1 代码复用性差:需要为每种动物写一个wei方法
    • 2 代码扩展性差:如果有新的动物类型 需要修改饲养员类 添加新的wei方法
    • 3 代码耦合度高:饲养员类中直接使用dog类
  • 使用多态

public static void main(String[] args) {
		//5 调用方法时   传递任意子类类型的对象
		Cat2 c=new Cat2("波斯猫");
		wei(c);
		Dog2 d=new Dog2("哈趴狗");
		wei(d);
    }
	//4 定义方法时 不要把形参定义为具体的子类类型  定义为父类类型
	public static void wei(Animal2 d) {//此方法只能实现喂狗
		d.eat();
		d.yunDong();
	}

}
//1创建父类: 抽取子类中共同的数据和功能写成父类
abstract class Animal2{
	String name;
	abstract void eat();//eat方法方法体无法实现:信息不完整
	abstract void yunDong();
}
//2让所有子类继承父类
class Dog2 extends Animal2{
	public Dog2 (String name) {
		this.name=name;
	}
	//3根据子类的需求 实现父类的抽象方法
	void eat() {
		System.out.println("狗:"+name+"正在吃骨头!");
	}
	void yunDong() {
		System.out.println("狗"+name+"看门!");
}
}
class Cat2 extends Animal2{
	public Cat2(String name) {
		this.name=name;
	}
	void eat() {
		System.out.println("猫:"+name+"正在吃鱼!");
	}
	void yunDong() {
		System.out.println("猫"+name+"晒太阳!");
	}

多态使用场景1:定义方法参数列表时 定义为父类类型 这样就可以传递任意子类类型的对象

情况2

设计一个台灯类Lamp
其中台灯有开灯(on)这个方法,
设计俩个灯泡类
其中有红灯泡(RedBulb) 和绿灯泡(GreenBulb)
他们都有一个发亮的方法,请设计出一段代码可以使台灯开启灯泡发亮

  • 不使用多态
public class LianXi1_1 {
//不使用多态
	public static void main(String[] args) {
		//创建灯泡对象
		RedBulb1 r1=new RedBulb1();
		GreenBulb1 g1=new GreenBulb1();
		//创建台灯对象
		Lamp1 l1=new Lamp1();
		//给台灯对象的属性赋值
		l1.r=r1;
		l1.g=g1;
        //调用台灯对象的方法
		l1.on();
       }
}
class Lamp1{//台灯类
	//灯泡是台灯的一个数据
	RedBulb1 r;//定义成员变量记录需要安装的红灯泡
	GreenBulb1 g;//定义成员变量记录需要安装的绿灯泡
	void on() {
		if (r!=null) {r.light();}
		if (g!=null) {g.light();}
		
	}
}
class RedBulb1{
	void light(){
		System.out.println("红灯泡  发光:红");
	}
}
class GreenBulb1{
	void light(){
		System.out.println("绿灯泡  发光:绿");
	}
}
  • 缺点

    • 1:代码复用性差:有几种灯泡类型 在台灯类中就需要定义几个属性 而且在on方法中进行多次if判断
    • 2:扩展性差:有新灯泡类型 需要更改Lamp类 添加新属性 修改on方法
    • 3:耦合性强
  • 使用多态

public class LianXi1_2 {
//使用多态
	public static void main(String[] args) {
	    //创建灯泡对象
		RedBulb r1=new RedBulb();
		GreenBulb g1=new GreenBulb();
		//创建台灯对象
		Lamp l1=new Lamp();
		//给台灯对象的属性赋值
		l1.b=r1;
		l1.b=g1;
		//调用台灯对象的方法
		l1.on();
	}
    class Lamp{//台灯类
	//灯泡是台灯的一个数据
	//定义父类类型的成员变量
	Buib2 b;
	void on() {
		if (b!=null) {b.light();}
	}
}
//抽取子类中共同数据和功能形成父类
abstract class Buib2{
	abstract void light();
}
//让所有子类继承父类
class RedBulb extends Buib2{
	//根据子类需求  实现父类方法
	void light() {
		System.out.println("红灯泡  发光:红");
	}
}
class GreenBulb extends Buib2{
	void light() {
		System.out.println("绿灯泡  发光:绿");
	}
}

多态使用场景2:定义成员变量时 定义为父类类型 这样就可以赋值任意子类类型的对象

情况3

三种类型:circle square rect三种类型 都有各自的属性 都有打印周长和打印面积的方法
写一个方法 传递一个int参数n n>1 返回一个长方形对象 n<1 返回一个正方形对象
n=1 返回一个圆形对象

  • 只能通过多态实现
public class LianXi1_3 {
	
	public static void main(String[] args) {
          Shape s=get(1);//多态
          s.printZC();
          s.printMJ();
	   }
    	//4 定义返回值类型时   定义为父类类型
	public static Shape get(int n) {
		if (n>1) {return new Rect(3, 2);}
		if (n<1) {return new Squarel(1);}
		return new Circle(1);
	}
    abstract class Shape{
	public abstract void printZC();
	public abstract void printMJ();
}
//2 所有子类继承父类
class Circle extends Shape{
	double r;
	final double PI=3.14;
	public Circle(double r) {this.r=r;}
	//3 子类根据自己的需求  实现父类的方法
	public void printZC() {System.out.println("圆 周长:"+2*PI*r);}
	public void printMJ() {System.out.println("圆 面积:"+r*PI*r);}
}
class Squarel extends Shape {
	double bianChang;
	public Squarel (double bianChang) {this.bianChang=bianChang;}
	public void printZC() {System.out.println("正方形  周长:"+bianChang*4);}
	public void printMJ() {System.out.println("正方形 面积:"+bianChang*bianChang);}
}
class Rect extends Shape{
	double chang,kuan;
	public Rect (double chang,double kuan) {this.chang=chang;this.kuan=kuan;}
	public void printZC() {System.out.println("长方形  周长:"+2*(chang+kuan));}
	public void printMJ() {System.out.println("长方形:"+chang *kuan);}
}

多态使用场景3:定义方法返回值类型时 定义为父类类型 这样就可以返回任意子类类型的对象

情况4

创建一个数组 :装2个圆、2个长方形、2个正方形

  • 只能通过多态实现
public static void createArray() {
		Circle c1=new Circle(1);
		Squarel s1=new Squarel(2);
		Rect r1=new Rect(2, 1);
		Circle c2=new Circle(11);
		Squarel s2=new Squarel(21);
		Rect r2=new Rect(21, 11);
		//定义数组必须明确:元素类型+元素个数
		Shape[] arr=new Shape[] {c1,c2,s1,s2,r1,r2};//多态
	}

多态使用场景4:定义数组元素类型时 定义为父类类型 这样就可以装任意子类类型的对象

总结: 定义方法参数列表时、定义方法返回值类型时、定义类的成员变量时、定义数组元素类型时,都定义为父类类型,这样就可以传递、返回、赋值、装任意子类类型的对象定义时定义父类类型 使用时使用子类类型的对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值