Java 学习笔记——多态(实例详解)
就比如猫,狗,狼都是动物,我们可以说猫是动物,说狗是动物
但我们不能说动物是猫,动物是狼。也不能说猫是狗,或者狗是狼。
上面这几点都会在多态中体现出来
多态的前提:
类之间要有继承的关系
子类要有对父类方法的重写(不重写也不会报错,但这样体现不出来多态的意义)
父类的引用变量指向子类对象
下面看一个多态的简单例子
class Animal{
public void eat(){
System.out.println("动物要进食");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫咪要吃饭");
}
}
public class Demo1 {
public static void main(String[] args) {
//从右往左念,猫咪是动物
//new Cat()已经创建了一个 Cat 类的对象,在堆内存之中
//Animal 类的引用变量指向了 Cat 类的子类对象
Animal a = new Cat();
//这里会优先调用子类的重写方法
a.eat();
}
}
结果为
这里需要注意的是,虽然是父类的引用变量,但实际上调用 eat()方法时,调用的是子类重写后的 eat()方法
如果对重写不了解的话,可以看下面链接里面的博客
多态访问成员特点
1、成员变量
编译看左边,运行看左边
2、构造方法
创建子类对象的时候,先访问父类的构造方法,先对父类的数据进行初始化
3、成员方法
编译看左边,运行看右边
因为子类的成员方法存在重写,所以运行访问的时候看右边
4、静态的成员方法:
编译看左边,运行看左边
静态的随着类的加载而加载
由于被 static 修饰的都是与类有关系的,所以它算不上重写
所以,编译的时候看左边,运行访问的时候也看左边
这里的左边指的是父类的引用变量,右边指的是子类的对象
这个单独看文字比较难懂,所以下面还是要看几个例子
首先是第一条,成员变量,编译看左边,运行看左边
class Animal{
int num =10;
public void eat(){
System.out.println("动物要进食");
}
}
class Cat extends Animal{
int num = 20;
public void eat(){
System.out.println("猫咪要吃饭");
}
}
public class Demo1 {
public static void main(String[] args) {
Animal a = new Cat();
System.out.println(a.num);
}
}
输出结果为 10
编译和运行都看左边的意思是,输出的结果根据父类的属性值来定,而不是子类
然后是第二条,可以看这篇博客的后半部分,关于构造方法调用顺序的详细解释
[关于构造方法调用
顺序的详细解释]( )
第三条成员方法,编译看左边,运行看右边
package test1;
class Father1{
public Father1() {
}
public void show(){
System.out.println("父类的 show 方法");
}
}
class Son1 extends Father1{
public Son1() {
}
public void show(){
System.out.println("子类的 show 方法");
}
}
public class duotaiDemo3 {
public static void main(String[] args) {
Father1 f = new Son1();
f.show();
}
}
结果为
而当子类没有重写这个方法时,会从父类中继承该方法,调用的时候也是调用这个方法
package test1;
class Father1{
public Father1() {
}
public void show(){
System.out.println("父类的 show 方法");
}
}
class Son1 extends Father1{
public Son1() {
}
// public void show(){
// System.out.println("子类的 show 方法");
// }
}
public class duotaiDemo3 {
public static void main(String[] args) {
Father1 f = new Son1();
f.show();
}
}
编译看左边的意思是编译过程中看父类中是否有这个方法
运行看右边的意思是运行过程中实际调用的方法是子类中重写后的方法
第四条静态的成员方法
class Animal{
int num =10;
public void eat(){
System.out.println("动物要进食");
}
public static void sleep(){
System.out.println("动物要休息");
}
}
class Cat extends Animal{
int num = 20;
public void eat(){
System.out.println("猫咪要吃饭");
}
public static void sleep(){
System.out.println("猫咪要睡觉");
}
}
public class Demo1 {
public static void main(String[] args) {
Animal a = new Cat();
//System.out.println(a.num);
Animal.sleep();
Cat.sleep();
}
}
结果为
因为是用类名调用,所以都是打印相对应的结果
介绍完多态访问成员的特点后,我们需要思考一个问题,为什么要使用,以及使用多态有什么好处
下面来看这个例子
class Animal{
public void eat(){
System.out.println("动物要进食");
}
public void sleep(){
System.out.println("动物要休息");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫咪要吃饭");
}
public void sleep(){
System.out.println("猫咪要睡觉");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗要啃骨头");
评论