Java 多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态的优点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
多态存在的三个必要条件
继承
重写
父类引用指向子类对象:Parent p = new Child();
重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
@Override(重写一个方法的声明)
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。
在面向对象原则里,重写意味着可以重写任何现有方法。
public class Animal {
public int age = 3;
public void eat(){
System.out.println("动物进食.....");
}
}
public class Cat extends Animal{
public int age = 2;
public int weight = 10;
@Override
public void eat(){
System.out.println("猫吃鱼...");
}
public void palyGame(){
System.out.println("猫抓老鼠玩....");
}
}
public class Dog extends Animal{
public int age = 4;
public String name = "旺财";
@Override
public void eat(){
System.out.println("狗吃骨头....");
}
public void work(){
System.out.println("狗看家....");
}
}
如果在编译时和运行时类型不一致,就出现了对象的多态性。
多态情况下成员方法,
看左边: 看的是父类的引用(父类中不具有子类特有的方法)
看右边 看的是子类的对象(实际运行时的子类重写父类的方法)
成员变量:不具备多态性,只要看引用变量声明的类型即可。
总结:
成员方法:编译看左边 运行看右边
成员变量:编译看左边 运行看左边
虚函数
虚函数的存在是为了多态。
Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是Java的默认行为。如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。
Animal a = new Animal();
a.eat();//动物进食
// 父类引用指向子类对象
Animal a1 = new Cat();
a1.eat();// 猫吃鱼
//a1.palyGame();//访问不到
System.out.println(a1.age);//3
Animal a2 = new Dog();
a2.eat();//狗吃骨头
System.out.println(a2.age);//3
多态的转型
基本类型的类型转换:
自动类型转换:小的数据类型可以自定转换为大的数据路诶性
强制类型转换:可以把大的数据类型强制转换为小的数据类型,与可能造成数据的精度损失。
java中对象的强制类型转换称为造型。
- 从子类到父类类型的转换可以自动进行。
- 从父类到子类的类型转换必须通过强制转换实现
- 无继承关系的引用类型间的转换是非法的
将有子类到父类的类型转换 称为向上转型
将有父类到子类的类型转换 称为向下转型,需要强制转换
instanceof
作用就是检验某一个引用是否是另一个类的实例对象。 返回值是boolean类型
if(ac instanceof Cat){
Cat cat = (Cat) ac;
cat.play();
}
继承成员变量和继承方法的区别
若子类重写父类的方法,就意味着子类中定义的方法彻底覆盖了父类中的同名方法,系统将把父类中的方法转移到子类。
对于实例变量则不存在这样的现象,即使子类定义了与父类完全相同的实例变量 这个实例变量依然不可能覆盖父类中的实例变量。