前言
刚开始学Java的时候对多态这个概念一直没弄太明白,随着后面的学习无意中都在用着多态,又看了一些文章决定整理一下!
举例
创建一个Person类,Student类继承Person类,并分别创建子类特有、父类特有、子类和父类共有的方法。
Person类
public class Person {
private String name;
private Integer age;
public void eat(){
System.out.println("我饿了!");//子类和父类共有的方法
}
public void tired(){//父类特有的方法
System.out.println("我累了!");
}
}
Student类
public class BoyStudent extends Person {
public void eat(){//子类和父类共有的方法
System.out.println("我要吃饭!!");
}
public void study(){//子类特有的方法
System.out.println("我正在学习!!");
}
}
public class GirlStudent extends Person {
public void eat(){//子类和父类共有的方法
System.out.println("我要吃饭饭!!");
}
public void study(){//子类特有的方法
System.out.println("我正在学习习!!");
}
}
测试类
public class Test {
public static void main (String [] args){
Person person=new BoyStudent();
person.eat();
person.tired();
((Student) person).study();
}
}
(1)形式上:父类的引用指向子类的对象。例如:
Person person=new Student();
Person person为父类的引用,后面为具体的子类
在jvm虚拟机中大概是这样的:
(2)当调用子类和父类共有的方法的时候,会执行子类重写后的方法
(3)当调用父类特有的方法的时候会执行父类的方法。
(4)当调用子类的特有的方法的时候要向下转型,否则,是无法调用子类的特有的方法的。
缺点:
它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的。
对多态的理解
- 接口的多种不同的实现既为多态。
- 将父类对象设置为一个或更多个子类对象(前面为父类对象,new 后面的为子类对象)
Person person=new BoyStudent();
Person person=new GirlStudent();
Person person=new ...Student();
Person person=new ...Student();
...
- 程序中定义的引用类型的变量调用的方法在编程的时候并不确定,当处于运行期间才确定(编译看左边,运行看右边)。这样不用修改源码就可以把变量绑定到不同的类实例上,让程序拥有了多个运行状态,这就是多态。
public class Worker extends Person {
public void eat(){
System.out.println("我饿了,我要吃饭!!");
}
public void work(){
System.out.println("今天继续搬砖!!");
}
}
public class Student extends Person {
public void eat(){
System.out.println("我要吃饭!!");
}
public void study(){
System.out.println("我正在学习!!");
}
}
也就是说,在定义父类的引用的时候运行的时候就可以指向两种不同的对象,调用eat方法后就会产生不同的效果,也就是说用同样的对象调用同样的方法但是做了不同的事情。
三要素
继承或接口实现(先决条件,没有继承就不会有子类对父类方法的重写)
重写(不同的子类对父类的方法进行重写之后才会体现父类的引用的多态)
父类引用指向子类对象(这是多态的具体实施)
例如:创建一个Person类作为父类,学生类和教师类作为子类。将学习作为子父类的公共的方法,子类可以重写父类的方法并且可以有自己特有的方法。父类的引用指向子类对象,此时,父类的引用只能调用父类特有的方法或者子父类共有的字类重写后的方法,调用子类特有的方法的时候需要向下转型。
多态的体现
Set <Student> students=new HashSet<Student>();
students.add(stu1);
Set<Student> students1=new LinkedHashSet<Student>();
students1.add(stu2);
HashSet类和LinkedHashSet类都实现了同一个接口Set,在上面的程序中,Set接口的引用,分别指向了不同的对象,调用名字相同但是功能不同的方法,体现出了多态。
其它
一般认为Java中的函数重载是一种静态多态,因为他需要在编译期决定具体调用哪个方法。而重写是只有在运行时期确定到底运行哪一个子类中的方法