多态
指的是一种事物的多种形态(状态)
例子:卵-->蝌蚪-->青蛙-->青蛙妈妈
实现多态的前提
1.类与类必须有继承关系
2.必须有方法的重写
核心:父类的指针(引用) 指向 子类的 对象(子类的空间)
public class Demo01 {
public static void main(String[] args) {
//本类的引用(指针)指向本类的对象(空间)
Man man = new Man();
man.eat();
//多态的对象创建方法
//父类指针指向子类的空间
Person1 aman = new Man();//父类的 引用(指针) 指向 子类对象(子类的空间)
aman.eat();
Person1 awoman= new Woman();
awoman.eat();
}
}
/*
* 需求: 创建 人类 男人类 女人类 都有一个吃的方法 人类 动物吃饭 男人 男人喝酒 女 女人化妆
*/
class Person1 {
public void eat() {
System.out.println("人吃饭");
}
}
class Man extends Person1 {
public void eat() {
System.out.println("男人喝酒");
}
}
class Woman extends Person1 {
public void eat() {
System.out.println("女人化妆");
}
}
多态如何使用成员变量
父类的引用指向子类的空间中 父类的那部分
编译:在子类中寻找父类的属性 如果找不到 就报错
运行:访问的是父类的成员变量
结论:当使用多态创建对象时 访问的成员变量 编译和运行都看父类
多态调用成员方法
编译:在子类中寻找父类的 成员方法 如果找不到就报错
运行:看子类的重写父类的方法
结论:重写方法时 编译看父类 运行看子类
public class Demo02 {
public static void main(String[] args) {
//多态的创建形式(画内存图)
Father fSon = new Son();
fSon.print();
System.out.println(fSon.num);
Son son = new Son();
son.print();
System.out.println(son.num);
}
}
class Father {
int num = 10;
public void print() {
System.out.println("我是父类的打印方法");
}
}
class Son extends Father {
int num = 20;
@Override
public void print() {
System.out.println("我是子类的打印方法");
}
}
多态的好处:
1.提高代码的复用性 提高效率 代码的维护性加强(继承)
2.代码的扩展性增强
坏处:使用多态方法创建对象时不能直接调用子类的特有方法
注意:使用多态调用方法时必须先向上转型 在向下转
public class Demo03 {
public static void main(String[] args) { //多态对象创建 //提升骗子逼格 //提升子类对象的类型 --向上转型 Person p = new PianZi(); p.speak(); //如何调用子类特有方法 //把骗子打回原形 //向下转型---强制类型转换 PianZi pianZi=(PianZi)p; //调用子类的特有方法 pianZi.hit(); } } class Person{ public void speak() { System.out.println("聊天"); } } class PianZi extends Person{ public void speak() { System.out.println("洗脑"); } //特有方法 public void hit() { System.out.println("打人 威胁人"); } } ![](https://img-blog.csdn.net/20180512102300941?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoYW53ZW5mZW5neXU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
多态的核心特点:提高方法扩展性;
举个例子
public class Demo04 {
public static void main(String[] args) {
Jian jian = new Jian();
fun(jian);
Dao dao = new Dao();
fun(dao);
}
// 使用多态的方法
public static void fun(WuQi wuQi) {
//调用子类中重写的方法
wuQi.hit();
//判断一下类型
//根据具体的类型进行向下转型
//判断 wuQi 是否属于 剑(类名)这个类的对象
if (wuQi instanceof Jian) {
//改武器就是一把剑
//向下转型
Jian j=(Jian)wuQi;
//调用特有的方法
j.LianJian();
}else if (wuQi instanceof Dao) {
Dao d= (Dao)wuQi;
d.LianDao();
}
}
}
class WuQi {
public void hit() {
System.out.println("武器打");
}
}
class Jian extends WuQi {
@Override
public void hit() {
System.out.println("剑-- 舞衣下");
}
public void LianJian() {
System.out.println("练习剑法");
}
}
class Dao extends WuQi {
@Override
public void hit() {
System.out.println("砍人");
}
public void LianDao() {
System.out.println("练习刀法");
}
}
上面个例子 扩展性体现在:如果我们要修改调用剑或者刀特有方法 只要从武器这个类入手就行
不需要 单独堆剑 或者 刀 进行分别调用;
下面有个练习 有时间看看
package com.lanou3g;
/*
* 铁桶僵尸 血量
* 方法:每次被打减少2滴血 直到被打死 打印铁桶死了
*
* 门框僵尸
* 血量
* 方法:每次被打减少5滴血 直到被打死 打印 门框死了
*
* main函数中 封装一个 打僵尸的方法
* 无参 有参 set get
*/
public class Demo07 {
public static void main(String[] args) {
TieTong tieTong = new TieTong();
tieTong.setBlood(200);
hiJiang(tieTong);
}
public static void hiJiang(JiangShi jiangShi) {
jiangShi.hit();
}
}
class JiangShi {
// 成员变量私有化
private int blood;
// 无参 有参
public JiangShi(int blood) {
super();
this.blood = blood;
}
public JiangShi() {
super();
// TODO Auto-generated constructor stub
}
public void hit() {
System.out.println("僵尸被人殴打");
}
// set get 方法
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
@Override
public String toString() {
return "Jiang [blood=" + blood + "]";
}
}
class TieTong extends JiangShi {
// 被打方法重写
@Override
public void hit() {
while (true) {
//判断血量
if (this.getBlood() <= 0) {
System.out.println("铁桶僵尸死了");
break;//结束
}
//一次2滴血
this.setBlood(this.getBlood() - 2);
System.out.println("僵尸剩余血量" + this.getBlood());
}
}
}
class MengKuang extends JiangShi {
//别打方法重写
@Override
public void hit() {
//判断血量
if (this.getBlood() <= 0) {
System.out.println("僵尸死了");
return;//结束
}
//打一次减少5滴血
this.setBlood(this.getBlood() - 5);
System.out.println("僵尸剩余血量" + this.getBlood());
this.hit();//调自己
}
}