天天看点

Java学习随笔——多态

最近重新学习Java基础,有许多以前不知道的地方。随手记录下来,主要面向自己,能帮助到别人当然更好,如有错误和不足,还望指正。

多态的场景

  • 有继承关系
  • 有子类对父类方法的重写
  • 父类的应用指向子类对象
class Person{
	
}
class Student extends Person{}

public class MyTest {
	public static void main(String[] args) {
		
		Person a = new Student();
	}
}
           

口诀

1. 成员变量:

编译看左边,运行看左边

//父类
class Animal{
	private String name = "ergo";
	public int age = 10;
	
	public Animal() {}
	public Animal(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	//非静态成员方法
	public void show() {
		System.out.println("----父类非静态方法----");
	}
	
	//静态成员方法
	public static void func() {
		System.out.println("----父类静态方法----");
	}
}
           
//子类
class Dog extends Animal{
	
	private String color = "红色";
	public	int size = 20;
	
	public void play() {
		System.out.println("play");
	}
	
	//重写父类show()方法
	@Override
	public void show() {
		System.out.println("子类重写父类的非静态方法");
	}
	
	public static void func() {
		System.out.println("子类静态方法");
	}
}
           
public class Demo {
	public static void main(String[] args) {
		Animal dog = new Dog();
		//编译通过,因为父类有age属性
		System.out.println(dog.age);	
		//编译不通过,因为父类没有size属性
		//System.out.println(dog.size);
	}
}
           
10

可以看出,对于成员变量,不管是编译还是运行,都依据父类的。

2. 成员方法:

编译看左边,运行看右边

在上面的代码中,我们在Dog类中重写了Animal类的非静态方法show(),还添加了子类独有的方法play()。接下来用创建的对象来调用这些方法观察下结果。

public class Demo {
	public static void main(String[] args) {
		Animal dog = new Dog();
		dog.show();
		//报错,因为父类中没有play()方法。
		//dog.play();		
	}
}
           
子类重写父类的非静态方法

由于父类中没有play()方法,所以dog.play()语句不能通过编译;而子类重写了父类的show(),执行的其实是子类重写后的show()方法。这也是为什么说重写是多态的前提之一。

3. 静态方法:

编译看左边,运行看左边

严格意义上来说,对静态方法并不能算重写,因为“重写”只适用于实例方法,而静态方法是属于类的,并不需要实例化对象去调用,不实例化也就不存在多态了。所以虽然形式上是重写的写法,但并不能达到重写的效果。