1.多态的概念
多态字面意思就是多种形态,具体点就是完成某个行为时,不同的对象完成时产生不同的状态。
总之,同一件事情,发生在不同的对象身上,会有不同的结果。
2.多态的实现条件。
在java中要实现多态,必须要满足如下几个条件,缺一不可:
1. 继承关系上:向上转型
2. 子类有和父类同名的重写方法
3. 通过父类对象的引用,调用重写的方法
完成以上三个条件,就会发生动态绑定,动态绑定是多态的基础。
多态的体现:在代码运行时,传递不同类对象时,会调用对应类中的重写方法。
class Animals{ public String name; public int age; public Animals(String name,int age){ this.name=name; this.age=age; } public void eat(){ System.out.println(this.name+"正在吃饭"); } } class Dogs extends Animals{ public Dogs(String name, int age){ super(name,age); } public void bark(){ System.out.println(this.name+"正在汪汪叫~"); } //方法重写 @Override //注解 public void eat() { System.out.println(this.name+"正在吃狗粮"); } } class Cats extends Animals{ public Cats(String name, int age){ super(name,age); } public void mimi(){ System.out.println(this.name+"正在喵喵叫~"); } //方法重写 @Override //注解 public void eat() { System.out.println(this.name+"正在吃猫粮"); } } public class Text { public static void main(String[] args) { //animal这个引用 指向了Dogs类的对象,向上转型直接赋值 Animals animal=new Dogs("赛虎",10); animal.eat();//父类的eat System.out.println("===="); //animal这个引用 指向了Cats类的对象,向上转型直接赋值 Animals animal1=new Cats("菲菲",15); animal1.eat(); } }
与上述代码中向上转型方式不同,但原理相同。
3.重写
重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
public void eat(){ System.out.println(this.name+"正在吃饭"); } public void eat() { System.out.println(this.name+"正在吃狗粮"); } public void eat() { System.out.println(this.name+"正在吃猫粮"); }
重写规则:
1.一般最基本的:返回值、参数列表、方法名必须一样。
2.被重写的方法的访问修饰限定符在子类中要大于等于在父类中的,即访问权限不能比父类中被重写的方法的访问权限更低,例如如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected。
3.父类被static、private,final修饰的方法、构造方法都不能被重写。
4.重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验。
方法重载(overloading)是一个类的多态性表现,而方法重写(overriding)是子类与父类的一种多态性表现。
重写设计原则:对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。
例如:几十年前的手机,只能打电话,发短信,来电显示只能显示号码,而今天的手机在来电显示的时候,不仅仅可以显示号码,还可以显示头像,地区等。在这个过程当中,我们不应该在原来老的类上进行修改,因为原来的类,可能还在有用户使用,正确做法是:新建一个新手机的类,对来电显示这个方法重写就好了,这样就达到了我们当今的需求了。
静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表方法重载。
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。