多态性
1 直白理解父类的引用指向子类的对象
//1、父类引用指向子类对象
//它是一个List对象,有些ArrayList有但是List没有的属性和方法,它就不能再用
//只能用List对象和ArrayList共有的方法
List<Integer> list = new ArrayList<Integer>();
// 2、子类引用指向子类对象
// 他是一个ArrayList对象,是List的子类,继承了List的所有方法
//因此可以用ArrayList和List的所有方法
ArrayList<Integer> arrayList = new ArrayList<Integer>();
那么为什么第二种方法多,反而不用呢,这就涉及到了面向接口编程的思想之所以要用父类来new子类,而不是直接用子类new
子类,是因为假如以后要重构代码,你觉得这里不应该用ArrayList而是应该用LinkedList,采用第一种方式写的代码,只需要修改这一行代码即可,然而用第二种方式写的代码就可能需要修改很多行代码(因为他可能用到了子类独有的方法)。
2 多态性
- 1.理解多态性:可以理解为一个事物的多种态性。
- 2.何为多态性:
- 对象的多态性:父类的引用指向子类的对象(或子类的对象赋值给父类的引用)
- 3.多态的使用:虚拟方法调用
- 有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法简称:编译时,看左边;运行时,看右边。若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism) 多态情况下,
“看左边”:看的是父类的引用(父类中不具备子类特有的方法)
“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法) - 4.多态性的使用前提:
-
① 类的继承关系
-
② 方法的重写
- 5.对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)
2.1示例
/*
* 多态性应用举例
*/
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new Dog());
test.func(new Cat());
}
public void func(Animal animal){ //Animal animal = new Dog();
animal.eat();
animal.shout();
}
//如果没有多态性,就会写很多如下的方法,去调用
public void func(Dog dog){
dog.eat();
dog.shout();
}
public void func(Cat cat){
cat.eat();
cat.shout();
}
}
class Animal{
public void eat(){
System.out.println("动物,进食");
}
public void shout(){
System.out.println("动物:叫");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void shout() {
System.out.println("汪!汪!汪!");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void shout() {
System.out.println("喵!喵!喵!");
}
}
mysql 等数据库操作的话,需要更换数据库,那么就能使用多态性的体现,省去了很多繁琐的步骤。
对象的多态性只适用于方法,不适用于属性
3 重写的规则
重写是非static的
① 子类重写的方法的方法名和形参列表必须和父类被重写的方法的方法名、形参列表相同;
② 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限,
特殊情况: 子类不能重写父类中声明为private权限的方法;
③ 返回值类型:
父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void;
父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类;
父类被重写的方法的返回值类型如果是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须是:double)。
④ 子类方法抛出的异常不能大于父类被重写的方法抛出的异常;
注意:子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。
因为static方法是属于类的,子类无法覆盖父类的方法。
4 Super关键字
super可以用来调用:属性、方法、构造器.
4.1 super的使用
3.1 我们可以在子类的方法或构造器中,通过"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯去省略这个"super."
3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
3.3 特殊情况:当子类重写了父类中的方法后,我们想在子类的方法中调用父类中被重写的方法时,必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
4.2 super调用构造器
4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)“只能二选一,不能同时出现。
4.4 在构造器的首行,既没有显式的声明"this(形参列表)“或"super(形参列表)”,则默认的调用的是父类中的空参构造器。super()
4.5 在类的多个构造器中,至少有一个类的构造器使用了"super(形参列表)”,调用父类中的构造器。
《插入一条:赋值符号左右两边类型一致,要么是自动类型提升》
总结:向上转型 父类 父类对象 = 子类实例
1.父类有的方法,都可以调用,如果被子类重写了,则会调用子类的方法。
2. 父类没有的方法,而子类存在,则不能调用。
3.向上转型只对方法有影响,对属性没影响。属性不存在重写。*/
5 instanceof关键字的使用
使用情景:为了避免在向下转型的时候出现异常 我们再向下转型之前。先进性instance of的判断,一旦返回true 就进行向下转型 如果返回false 不进行向下转型
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。