1. 理解多态性:可以理解为一个事物的多种态性。
2.何为多态性:
对象的多态性:父类的引用指向子类的对象(或子类的对象赋值给父类的引用)。
3. 多态的使用:虚拟方法调用
有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法。简称:编译时,看左边;运行时,看右边。
若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism).
多态情况下,
"看左边":看的是父类的引用(父类中不具备子类特有的方法〕
"看右边":看的是子类的对象(实际运行的是子类重写父类的方法)。
4. 多态性的使用前提
①要有类的继承关系。
②要有方法的重写。
5. 对象的多态性:只适用于方法,不适用于属性(属性:编译和运行都看左边)。
来看以下几段代码:
1、Person类
public class Person {
String naem;
int age;
int id=1001;
public void eat() {
System.out.println("人吃饭!");
}
public void walk() {
System.out.println("人走路!");
}
}
2、Woman类
public class Woman extends Person{
boolean isBeauty;
public void goShopping(){
System.out.println("女人喜欢购物!");
}
public void eat(){
System.out.println("女人少吃,为了减肥。");
}
public void walk(){
System.out.printin("女人,窈窕的走路! ");
}
}
3、Man类
public class Man extends Person{
boolean isSmoking;
public void earnMoney(){
System.out.println("男人负责工作养家 !");
}
public void eat(){
System.out.println(" 男人多吃肉,长肌肉");
}
public void walk(){
System.out.println(" 男人霸气的走路");
}
}
4、Persontest类
public class Persontest {
public static void main(String[] args) {
Person p1= new Person();
p1.eat();
Man man = new Man();
man.eat();
man.age =25;
man.earnMoney();
//***************
//父类的引用指向子类的对象:多态性(对象的多态性!)
Person p2=new Man();//多态性(对象的多态性!)
Person p3=new Woman();
System.out.println();
//多态的使用:当调用子父类同名同参的方法时,实际调用的是子类中重写的方法-----虚拟方法调用
p2.walk();//按ctrl点以下,跑到父类
p2.eat();
p3.walk();
p3.eat();
// p2.earnMoney();//不能调子类特有的方法!
System.out.println(p2.id);//1001,父类中属性。
}
}
多态性应用举例:
public class Animaltest {
public static void main(String[] args) {
Animaltest test =new Animaltest();
test.fun(new Dog());
test.fun(new Cat());
}
public void fun(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{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("狗,吃骨头!");
}
@Override
public void shout() {
// TODO Auto-generated method stub
System.out.println("汪汪汪!");
}
}
class Cat extends Animal{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("猫,吃🐟!");
}
@Override
public void shout() {
// TODO Auto-generated method stub
System.out.println("喵喵喵!");
}
}
虚拟方法的补充:
从编译和运行的角度看:
重载,是指允许存在多个同名方法,而这些方法的参数不同。
编译器根据方法不同的参数表,对同名方法的名称做修饰。
对于编译器而言,这些同名方法就成了不同的方法。
它们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定“;而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
引用一句 Bruce Eckel 的话:“不要犯傻,如果它不是晚绑定,它就不是多态。“