基本概念:
1.多态性是指一个对象对应多种不同的类型,比如猫具备猫的属性,又具备动物的属性。
2.多态在代码中的体现:父类或接口的引用指向其子类的对象。
3.多态的优点:提高了代码的扩展性,前期定义的代码可以使用后期的内容。
4.多态的弊端:前期定义的内容不能使用后期内容的特有属性。
5.多态实现的前提:必须要有关系(继承或实现),要有覆盖。
方法的多态性:
·方法重载:同名方法由于参数类型,个数的不同而执行不同的方法体
·方法覆盖:父类的同一个方法可能由于实例化子类的不同而有不同的实现
对象的多态性:(前提:方法覆盖)
·向上转型:【自动】父类 父类对象 = 子类实例;
·向下转型:【强制】子类 子类对象 = (子类)父类实例;
1.转型
看以下例子:
class Animal{
public Animal() {}
}
class Cat extends Animal{
public Cat() {}
}
public class Test {
public static void main(String[] args) {
// 向上转型,隐藏了子类对象,目的是限制对于子类对象特有属性的访问
Animal a = new Cat();
// 向下转型,目的是为了访问子类的特有属性
Cat c = (Cat)a;
}
}
误区:
Animal a = new Animal();
Cat = (Cat)a;
此代码会出现classCastException的错误,因为对于转型来说,自始至终都是子类对象在做类型转换操作。即只有向上转型之
后才能执行向下转型。
对于子类重写父类的方法,向上转型后调用的仍是子类的方法。
看以下例子:
class Animal{
public Animal() {}
void show() {
System.out.println("Animal show");
}
}
class Cat extends Animal{
public Cat() {}
void show() {
System.out.println("Cat show");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Cat();
a.show();
}
}
结果是:Cat show
2.instanceof关键字
用于判断对象的具体类型,只能用于引用数据类型的判断。以下资源来自于菜鸟教程
格式:对象 instanceof 类; 返回值为boolean型。
通常在向下转型时使用instanceof关键字来判断健壮性。
3.多态时成员变量的特点
编译时:参考引用变量所属的类中是否有调用的成员变量,若没有则编译出错。
运行时:参考引用变量所属的类中是否有调用的成员变量,并运行该类中的变量。
简单说就是都看等号左边的类。
看以下例子:
class Fu{
int num = 10;
Fu(){}
}
class Zi extends Fu{
int num = 8;
Zi(){
}
}
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);
}
}
结果:10
若是父类中没有num变量,则编译出错。
4.多态时非静态成员方法的特点
编译时:参考引用变量所属的类中是否有调用的成员方法,若没有则编译出错。
运行时:参考对象所属的类中是否有调用的成员方法,若没有则执行父类中的同名方法。
简单说就是:编译时看等号左边,运行时看等号右边。由对象调用方法,是方法的动态绑定。
看例子:
class Fu{
Fu(){}
void show() {
System.out.println("fu show");
}
}
class Zi extends Fu{
Zi(){}
void show() {
System.out.println("zi show");
}
}
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
f.show();
}
}
结果:zi show
若是屏蔽掉子类的show()方法,即:
class Zi extends Fu{
Zi(){}
/* void show() {
System.out.println("zi show");
} */
}
则结果是:fu show
5.多态时静态成员方法的特点
编译运行时都参考对象所属的类中是否有调用的成员方法,若没有则不通过编译。
看例子:
class Fu{
Fu(){}
static void show() {
System.out.println("fu show");
}
}
class Zi extends Fu{
Zi(){}
static void show() {
System.out.println("zi show");
}
}
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
f.show();
}
}
结果是:fu show
回过头来想想其实静态方法是静态绑定的,不依赖于对象,个人认为静态方法和静态变量不涉及多态,可以直接通过类名调用。
6.多态性的应用
主要通过对象的向上转型来实现接收参数的统一。
看例子:
/** 对于吃早餐这个行为来说,不管什么人吃,吃的动作怎样,都是吃 */
class Person{
void eat(){
System.out.println("eat food");
}
}
class Student extends Person{
void eat(){
System.out.println("eat food slowly");
}
}
class Worker extends Person{
void eat() {
System.out.println("eat food quickly");
}
}
class Teacher extends Person{
void eat() {
System.out.println("eat food gently");
}
}
public class A {
// 所有的人不论吃相统一的方法进行
public static void eatBreakFast(Person1 per) {
per.eat();
}
public static void main(String[] args) {
eatBreakFast(new Student());
eatBreakFast(new Worker());
eatBreakFast(new Teacher());
}
}
结果:
eat food slowly
eat food quickly
eat food gently
如果不使用多态,则会多次重载eat()方法,当子类的类型非常多时,这是很不容易的。