多态
- 1.1 概念
- 1.2 实现条件
- 1.3 方法重写(override)与方法重载(overload)
- 1.4 向上转型
- 1.5 向下转型
1.1 概念
同样的一个方法/行为,经过不同的对象,表现出不同的行为,这样的现象就称为多态。
举例说明:打印机进行打印
对于不同的打印机对象,使用相同的打印方法,表现出不同的行为。(黑白打印对象–>打印方法–>打印黑白的图像;彩色打印对象–>打印方法–>打印彩色的图像)
两不同,一相同
不同的对象,调用相同的方法,表现出不同的行为,称为多态!
1.2 实现条件
java中要想实现多态,必须同时满足以下三个条件,缺一不可:
- 多态的实现必须依赖继承,在继承体系下才有多态。只有在继承关系的类之间才有多态可言。
- 子类必须要覆写父类中的方法。
- 通过父类的引用调用子类重写的方法。
Test类
public static void main()
{
Cat cat=new Cat("yy",1);
Dog dog=new Dog("xx",2);
fun(cat);
fun(dog);
}
public static void fun(Animal animal)
{
animal.eat();
}
不同:调用fun()方法时,传入了不同的Animal对象
一个是Dog类对象;一个是Cat类对象
相同:调用的都是eat方法
不同:根据不同对象,表现出了不同的eat行为
1.3 方法重写(override)与方法重载(overload)
-
方法重写:在有继承关系的类之间,子类定义了和父类除了权限不同以外,其他(方法名称、参数列表、返回值类型(向上转型除外))完全相同的方法称为子类重写了父类的方法。子类重写方法的权限>=父类方法。
-
方法重载:在同一个类中,定义了一组方法名称相同,参数列表不同,与返回值无关的一组方法,称为重载方法。
- 解释向上转型除外问题
方法重写,返回值类型可以为向上转型类的返回值,父类方法返回父类对象,子类重写的方法返回子类对象,因为子类对象天然是父类引用(is an),本质上返回值类型相同。
Animal类
{
public Animal(){}
public Animal test()
{
return new Animal;
}
}
Dog类
{
public Dog(){}
//子类中重写test方法,返回值为向上转型类的返回值:Dog is an animal
public Dog test()
{
return new Dog;
}
}
- 为什么重载没有权限问题?
同一个类中,所有东西均可见,与权限无关。 - 私有方法能否被重写?
方法重写,不包含私有方法的重写。私有继承,子类中都不清楚父类中包含此方法,因此不能重写。
所谓重写,在父类的现有方法上进行覆盖,前提是子类得清楚父类的方法。 - static方法是否存在重写?
不存在。首先,静态方法严格和类进行绑定,而多态即为不同的对象,而静态方法中就不包含对象的概念。 - 构造方法能否被重写?
不能。构造方法决定一个对象如何产生,如何赋值,不能在子类中给父类进行赋值操作。
重写就是在子类中修改了父类的原有方法的表现,以当前子类对象的方法为准。
- 静态绑定 和 动态绑定
- 静态绑定----方法重载:编译时,编译器根据用户传参的不同决定到底调用的是哪个方法。
- 动态绑定----方法重写:编译时无法确定到底调用的是哪个对象的 eat 方法,只有在运行时,根据具体传入的对象,才能决定到底调用的是哪个对象的 eat 方法,这叫做动态绑定。
即:运行时才明确调用的是哪个方法。
1.4 向上转型
天然发生,且是之后产生对象的主要方式。
语法:父类名称 父类引用=new 子类实例
//从右向左读,Dog is an animal,天然发生的向上转型
Animal animal=new Dog("66",5);
- 通过这个父类引用可以调用哪些属性和方法取决于父类中包含哪些属性和方法
- 调用的方法表现出的行为,需要看new的是哪个子类对象
向上转型的优点:参数统一化!!!
假设需要定义fun函数来接收所有的Animal
以及其子类对象,如果没有向上转型,则需要定义N个fun
函数来接收对象。即为函数重载。会出现大量的代码冗余,不方便进行子类的扩展。
存在向上转型则通过共同的父类引用animal
来指向不同的子类对象,fun
函数只需要定义一次。
缺点:只能调用所有子类共有的方法(在父类中定义了),子类独有的方法无法通过父类引用调用。
1.5 向下转型
语法:子类名称 子类引用=(子类名称)父类引用
要发生向下转型,必须先发生向上转型,否则会报错。需要强制类型转换,属于将大类型强制转换为小类型。
//大类型的引用指向小类型,需要强转,但是不一定成功
//除非animal引用本来就指向的是Dog对象才能转换
Dog dog =(Dog) animal
父类引用本身就指向的是子类对象,向下转型才能还原为当前这个子类引用;
反之,如果指向的不是子类对象,则无法向下转型,抛出类型转换异常ClassCaseException
可以使用Java中提供的关键字instanceof
来判断一个父类引用是否指向了一个子类实例
语法:引用名称 instanceof 类
返回值:布尔类型