一.多态的概述
某一事物,在不同时刻表现出来的不同状态
举例: Cat c=new Cat();
Animal a=new Cat();
猫可以是猫的类型。Cat m = new Cat();
同时猫也是动物的一种,也可以把猫称为动物。Animal d = new Cat();
多态的前提:
1:要有继承关系。
2:要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。
3:要有父类引用指向子类对象。
Father f = new Son();
举例如下:
public class Animal {
String name;
int age;
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫喜欢白天睡觉");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗趴在狗窝里睡觉");
}
}
public class MyTest {
public static void main(String[] args) {
//猫是猫类的一种
//Cat cat=new Cat();
//猫是动物的一种 ,多态
Animal an = new Cat(); //父类引用指向子类对象
an.name = "汤姆";
an.age = 12;
System.out.println(an.name);
System.out.println(an.age);
an.eat();
an.sleep();
an = new Dog();
an.sleep();
an.eat();
}
}
二.多态的成员访问特点
左(父类) =右(子类)
1:成员变量
编译看左边,运行看左边。
2:构造方法
创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
3:成员方法
编译看左边,运行看右边。当然如果子类没有从写访问的还是父类的
4:静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)
举例如下:
public class MyTest {
public static void main(String[] args) {
Fu fu = new Zi();
System.out.println(fu.num);
System.out.println(fu.price);
fu.show();
fu.test();
Fu.test();
Zi.test();
}
}
class Fu {
int num = 100;
double price = 20;
public Fu() {
System.out.println("父类的构造方法执行了");
}
public void show() {
System.out.println("fu show");
}
public static void test() {
System.out.println("fu 类的静态方法");
}
}
class Zi extends Fu {
int num = 200;
double price = 300;
public Zi() {
System.out.println("子类的构造方法执行了");
}
@Override
public void show() {
System.out.println("zi show");
}
public static void test() {
System.out.println("zi 类的静态方法");
}
}
三.多态的好处和弊端
好处:
1:提高了代码的维护性(继承保证)
2:提高了代码的扩展性(由多态保证)
举例如下:
public class Animal {
public void eat() {
System.out.println("吃饭");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
public class TestUtils {
//私有构造
private TestUtils() {
}
//多态实现的
public static void testEat(Animal an) { // Animal an=cat Animal an=dog Animal an=rabbit
an.eat();
}
public class MyTest {
public static void main(String[] args) {
//多态的好处:提高代码的扩展性。
//我现在要测试,吃饭的功能
Cat cat = new Cat();
TestUtils.testEat(cat);
Dog dog = new Dog();
TestUtils.testEat(dog);
//我们的入口类,在入口类中,一般我们只会提供一个main方法作为一个入口,不会在这个入口类中,提供其他的方法和成员变量,只是在main方法中创建其他类的对象,使用其他类。
}
}
弊端:
1.无法直接访问子类特有的成员。
四. 向上转型和向下转型
把父类的引用强制转换为子类的引用。(向下转型)
这样就可以解决多态中的弊端了
public class Animal {
String name;
int age;
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
public class Cat extends Animal {
int c = 20;
public void catchMouse() {
System.out.println("抓老鼠");
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫喜欢白天睡觉");
}
}
public class Dog extends Animal {
int d = 30;
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗趴在狗窝里睡觉");
}
public void lookDoor() {
System.out.println("狗看门");
}
}
public class MyTest {
public static void main(String[] args) {
Animal an = new Cat(); //多态就是向上转型
System.out.println(an.name);
System.out.println(an.age);
an.eat();
an.sleep();
//如果你想要访问子类特有的成员,可以向下转型。
Cat cat = (Cat) an; //向下转型
System.out.println(cat.c);
cat.catchMouse();
System.out.println("======================");
Animal an1 = new Dog(); //多态就是向上转型
System.out.println(an1.name);
System.out.println(an1.age);
an1.eat();
an1.sleep();
//向下转型
Dog dog = (Dog) an1;
System.out.println(dog.d);
dog.lookDoor();
}
}