多态
1.1 多态概述
同一个对象,在不同时刻表现出来的不同形态
举例:猫
猫的形态猫是猫: 猫 cat = new 猫();
猫的形态是动物: 动物 animal = new 猫() —> 父类的引用(animal ) 指向子类对象(new 猫())
这里猫在不同时刻表现出来的不同形态就是多态
多态的前提和体现:
1、有继承/实现关系
public class Animal { public void eat(){ System.out.println(“吃东西”); }}
2、有方法重写
public class Cat extends Animal{
@Override
public void eat() { System.out.println(“猫咪吃东西”); } }
3、有父类引用指向子类对象
public class AnimalDemo {
public static void main(String[] args) {
// 有父类引用 指向 子类对象
Animal animal = new Cat(); } }
1.2 多态的访问特点
成员变量: 编译看左边,执行看左边
成员方法: 编译看左边,执行看右边
// 父类
public class Animal {
public int age = 10;
public void eat(){ System.out.println(“吃东西”); } }
// 子类
public class Cat extends Animal{
public int age = 20;
public int weight = 10;
@Override
public void eat() { System.out.println(“猫咪吃东西”); }
public void playGame(){ System.out.println(“猫咪上树”); } }
// 公共类
public class AnimalDemo {
public static void main(String[] args) {
// 有父类引用 指向 子类对象 —> 多态的形式创建对象
Animal animal = new Cat();
System.out.println(animal.age);
// System.out.println(animal.weight);
animal.eat();
// animal.playGame(); } }
成员变量和成员方法访问不一样:因为成员方法里面包含重写,但是成员变量没有
1.3 多态的好处和弊端
多态的好处:提高了程序的扩展性
具体体现:定义方法的时候,使用方法类型作为参数,将来在使用的时候,使用具体的子类型参与操作
// 父类,定义一个eat()方法
public class Animal { public void eat(){ System.out.println(“吃东西”); }}
———————————————————————————————————————-
// 子类 Cat 重写eat()方法
public class Cat extends Animal{
@Override
public void eat() { System.out.println(“猫咪吃鱼”); } }
// 子类 Pig 重写eat()方法
public class Pig extends Animal{
@Override
public void eat() { System.out.println(“猪猪吃菜”); } }
// 子类 Dog 重写eat()方法
public class Dog extends Animal{
@Override
public void eat() { System.out.println(“狗吃包子”); }
// 子类特有的方法
public void watch(){ System.out.println(“狗狗开门”); } }
—————————————————————————————————————————-
// 公共类操作层
public class AnimalOperator {
/ // 定义一个方法 Cat c = new Cat();
public void useAnimal(Cat cat){ cat.eat(); }
// 定义一个方法 Dog dog = new Dog();
public void useAnimal(Dog dog){ dog.eat(); } /
// 因为cat类和dog类都继承了animal类
public void useAnimal(Animal animal){
// Animal animal = new Cat();
// Animal animal = new Dog();
// 成员方法: 编译看左边,执行看右边
animal.eat();
// animal.watch(); 多态无法访问子类特有的方法 } }
// 公共类
public class AnimalDemo {
public static void main(String[] args) {
// 创建AnimalOperator类的对象,并调用方法
AnimalOperator ao = new AnimalOperator();
// AnimalOperator类的对象的参数是Cat类
// 创建一个Cat类的对象,将cat对象传给方法
Cat cat = new Cat();
ao.useAnimal(cat);
Dog dog = new Dog();
ao.useAnimal(dog);
Pig pig = new Pig();
ao.useAnimal(pig); } }
多态的弊端:不能使用子类的特有功能
1.4 多态中的转型
1、向上转型
从子到父 — Fu fu = new Zi();
使用子类实例父类的对象,就是基础多态
父类引用指向子类对象
2、向下转型
从父到子 — Zi zi = (Zi)fu;
为实现子类的特有方法,实例子类的对象,并使用类转换(子类)父类的实例的对象
// 父类,定义一个eat()方法
public class Animal { public void eat(){ System.out.println(“吃东西”); }}
// 子类,重写父类eat()方法,定义了一个play()新方法
public class Cat extends Animal{
@Override
public void eat() { System.out.println(“猫猫吃鱼”); }
public void play(){ System.out.println(“躲猫猫”); } }
// 公共类
public class AnimalDemo {
public static void main(String[] args) {
// 向上转型,多态创建对象,父类引用指向子类对象
// 把父指向子,将子类对象赋值给父类
Animal animal = new Cat();
animal.eat(); // 输出:猫猫吃鱼
// animal.play(); 多态编译看左边的对象没有play()方法 报错
——————————————————————————————————————-
// 向下转型,父类引用animal强转换Cat子类对象
// 父类转成子类对象类似于类型转换 int a = (String)a
Cat cat=(Cat)animal;
cat.play(); } }
1.5 多态转型的内存图—没懂
// 公共类
public class AnimalDemo {
public static void main(String[] args) {
// 向上转型,多态创建对象,父类引用指向子类对象
// 把父指向子,将子类对象赋值给父类
Animal animal —>(父类引用对象)栈内存= new Cat();
// 多态访问成员变量方法,编译看左边成员看右边
animal.eat(); // 输出:猫猫吃鱼
// animal.play(); 多态编译看左边的对象没有play()方法 报错
——————————————————————————————————————-
// 向下转型,父类引用animal强转换Cat子类对象
// 父类转成子类对象类似于类型转换 int a = (String)a
Cat cat=(Cat)animal;
cat.play(); } }
1.6 多态案例:
猫和狗(多态)
需求:请采用多态的思想实现猫和狗的案例,并在测试类中进行测试
// 父类,定义一个eat()方法,两个参数:姓名,年龄
public class Animal {
public String name;
public int age;
public Animal() { }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public void eat(){ System.out.println(“动物吃食物”); }
public Animal(String name, int age) {
this.name = name;
this.age = age; } }
// 子类猫,重写父类eat()方法,一键生成alt+insert construct
public class Cat extends Animal{
// Cat子类继承Animal父类,一键生产construct
public Cat() { }
public Cat(String name, int age) { super(name, age); }
@Override
public void eat() { System.out.println(“猫吃鱼”); } }
// 子类狗,重写父类eat()方法,一键生产construct
public class Dog extends Animal{
public Dog() { }
public Dog(String name, int age) { super(name, age); }
@Override
public void eat() { System.out.println(“狗吃屎粑粑”); }
public void watch(){ System.out.println(“狗看门”); } }
// 公共类
public class AnimalTest {
public static void main(String[] args) {
// 采用多态的方式,父类引用指向子类对象,向下转型
// 无参构造方法
Animal animal = new Cat();
animal.setName(“奥利”);
animal.setAge(1);
System.out.println(animal.getName() + “,” + animal.getAge());
animal.eat();
System.out.println(“————————————————-“);
// 带参构造方法
animal = new Cat(“蓝胖子”, 2);
System.out.println(animal.getName() + “,” + animal.getAge());
animal.eat();
System.out.println(“————————————————-“);
animal = new Dog(“天天”, 4);
System.out.println(animal.getName() + “,” + animal.getAge());
Dog dog = (Dog) animal;
dog.watch();} }