目录
1.什么是多态
同一种事物在不同时刻表现的不同状态。
2..多态的条件
*有继承(包括接口的实现);
*有重写;
*父类引用指向子类对象。
3.多态中的调用
非静态的成员方法的调用:编译看左,运行看右
成员变量的调用:编译、运行都看左
静态成员方法的调用:编译、运行都看左
public class Animal {
private String name;
int age=10;
public void eat(){
System.out.println("动物类吃东西");
}
static void play(){
System.out.println("动物类玩");
}
}
public class Dog extends Animal{
int age=5;
@Override
public void eat() {
System.out.println("狗类吃肉");
}
static void play(){
System.out.println("狗类玩");
}
}
public class Test {
public static void main(String[] args) {
//使用父类类型进行成员方法访问时:编译看左边,执行看右边
Animal d=new Dog();
d.eat(); //狗类吃肉
//成员变量:编译和运行都看左边
System.out.println(d.age); //10
//静态方法:编译和运行都看左边
d.play(); //动物类玩
}
}
4.向上转型
为什么要向上转型?
首先我们来看以下代码
public class Animal {
public void eat(){
System.out.println("动物类吃东西");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗类吃肉");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
}
public class Person {
public void feedAnimal(Animal animal){
System.out.println("人喂动物");
animal.eat();
}
public void feedDog(Dog d) {
System.out.println("人喂狗");
}
public void feedCat(Cat c) {
System.out.println("人喂猫");
}
}
public class Test {
public static void main(String[] args) {
Person person=new Person();
Dog d=new Dog();
person.feedDog(d);
Cat c=new Cat();
person.feedCat(c);
}
}
我们由此可以发现:在以上非多态代码中,每次扩展新动物,就必须在Person类中构造方法。
对此进行改造:
public class Animal {
public void eat(){
System.out.println("动物类吃东西");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗类吃肉");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
}
public class Person {
public void feedAnimal(Animal animal){
System.out.print("人喂动物");
animal.eat();
}
}
public class Test {
public static void main(String[] arg){
/*由于有了继承关系,才可以用父类类型指向子类对象
向上转型 父类类型就可以表示任意的子类对象*/
Animal d=new Dog();
Animal c=new Cat();
Person person=new Person();
person.feedAnimal(d);
person.feedAnimal(c);
}
}
运行结果:
人喂动物狗类吃肉
人喂动物猫吃鱼
好处:将子类上升为父类,使用一个父类去表示任意的子类对象,提高程序的扩展性。
这也解释了多态:animal 既可以表示Dog,也可以表示Cat.
缺点:不能访问子类特有的方法。
5.向下转型
解决向上转型的缺点,访问子类特有的方法。
需要判断类型是否为指定类型。
public class Animal {
public void eat(){
System.out.println("动物类吃东西");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗类吃肉");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
}
public class Person {
public void feedAnimal(Animal animal){
System.out.print("人喂动物");
animal.eat();
//向下转型,将父类转为子类,传入子类对象.
if(animal instanceof Dog){//判断对象类型是否为指定类型。即判断animal所表示的对象类型是否为Dog类
Dog dog=(Dog)animal;
dog.play();
}
}
}
public class Test {
public static void main(String[] arg){
/*由于有了继承关系,才可以用父类类型指向子类对象
向上转型 父类类型就可以表示任意的子类对象*/
Animal d=new Dog();
Animal c=new Cat();
Person person=new Person();
person.feedAnimal(d);
person.feedAnimal(c);
}
}
运行结果:
人喂动物狗类吃肉
狗类玩
人喂动物猫吃鱼