一 : 多态
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:定义数组元素类型时 定义为父类类型 这样就可以装任意子类类型的对象