Polymorphism[多态]
简述:
面向对象多态性指的是:发送消息给某个对象,让该对象自行决定响应何种行为。
通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用
多态的三个前提条件:
- 多态发生在有继承关系的类之间
- 子类要对超类方法进行重写
- 父类引用指向子类对象
要了解多态,先了解casting(对象转型)的概念。
Casting[对象转型]
1.基类的引用类型变量可以是指向子类的对象。
2.一个基类引用不能访问子类对象新增加的成员(属性和方法 )
3.可以使用引用变量instaceof来判断该引用类型变量所“指向”的对象是否属于该类,或者该类的子类。
4. 子类对象可以作为基类对象使用,称为(upcasting)“向上转型”,反之,基类对象当做来使用称为(downcasting)“强制转换”。
实例
我们创建两个类,并且有继承关系,一个Animal类和Cat类
class Animal{ //每种动物都有名字 public String name; //对应初始化方法 Animal(String name){ this.name=name; } }
class Cat extends Animal{ //猫眼睛的颜色 public String eyesColor; //对应初始化 Cat(String name,String eyesColor){ super(name); this.eyesColor=eyesColor; } }
然后我们在验证 "1.基类的引用类型变量可以是指向子类的对象"
public class Casting{ public static void main(String[] args){ System.out.println("-------------------------------"); //创建Animal引用 Animal coco=null; //把子类对象赋给父类引用 coco=new Cat("mimi","black");//编译通过没问题 }
继续验证 " 2.一个基类引用不能访问子类对象新增加的成员(属性和方法 ) "我们把两个类增加方法
class Animal{ //每种动物都有名字 public String name; //对应初始化方法 Animal(String name){ this.name=name; } //动物叫声 public void say(){ System.out.println("name: "+name); } } //猫 class Cat extends Animal{ //猫眼睛的颜色 public String eyesColor; //对应初始化 Cat(String name,String eyesColor){ super(name); this.eyesColor=eyesColor; } public void miaow(){ System.out.println("猫叫"); } }我们用coco对象分别访问父类和子类的成员和方法
//coco调用Cat中所有的成员 coco.name="mici";//可以访问子类继承到的name变量 System.out.println(coco.name);//输出mici //coco.eyesColor="blue"; /*编译输出:cannot find symbol 说明父类引用看不到子类对象的成员,只能用父类Animal的视野看, 那就只能看见name咯 */coco.say();//编译运行没问题//coco.miaow(); /*编译输出:cannot find symbol 同样是编译出错找不到成员,所以向上转型父类引用只能看见自己传下去的东西咯 */
先面我们來用 instanceof 来测试首先
instanceof
instanceof是Java、php的一个二元操作符(运算符),和==,>,<是同一类东西。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是判断其左边对象是否为其右边类的实例,返回boolean类型的数据。可以用在继承中的子类的实例是否为父类的实现。
应用于上面的例子
全部代码,做了修改
//Have the courage to follow your heart and intuition. //对象转型。向上转型 //1.基类引用可以指向子类引用 //2.基类引用不能访问子类新增加的成员(方法属性) //3.可以用 instanceof判断引用类型是不是这个类或者子类 package me.animal; class Animal{ //每种动物都有名字 public String name; //对应初始化方法 Animal(String name){ this.name=name; } //动物叫声 public void say(Animal any){ System.out.println("name: "+any.name); //判断是什么类型猫啊狗啊,然后调用子类相应的成员 if(any instanceof Cat){ Cat cat=(Cat)any; System.out.println(" "+cat.eyesColor+" eyes"); } else if(any instanceof Dog){ Dog dog=(Dog)any; System.out.println(" "+dog.furColor+" fur"); } } } //猫 class Cat extends Animal{ //猫眼睛的颜色 public String eyesColor; //对应初始化 Cat(String name,String eyesColor){ super(name); this.eyesColor=eyesColor; } public void miaow(){ System.out.println("猫叫"); } } //狗 class Dog extends Animal{ //狗毛的颜色 public String furColor; //对应初始化 Dog(String name,String furColor){ super(name); this.furColor=furColor; } //狗叫的方法 public void bark(){ System.out.println("狗叫了..."); } } public class Casting{ public static void main(String[] args){ System.out.println("-------------------------------"); //创建Animal引用 Animal coco=null; //把子类对象赋给父类引用 coco=new Cat("mimi","black");//编译通过没问题 //coco调用Cat中所有的成员 coco.name="mici";//可以访问子类继承到的name变量 System.out.println(coco.name);//输出mici coco.say();//编译运行没问题 //coco.eyesColor="blue"; /*编译输出:cannot find symbol 说明父类引用看不到子类对象的成员,只能用父类Animal的视野看, 那就只能看见name咯 */ //coco.miaow(); /*编译输出:cannot find symbol 同样是编译出错找不倒成员,所以向上转型父类引用只能看见自己传下去的东西咯 */ coco. //创建猫狗对象 System.out.println("-------------------------------"); Cat nina=new Cat("nina","blue"); Dog hasx=new Dog("hasx","black"); Animal yoyo=new Animal("yoyo"); //用instanceof判断是不是对象属于类型 System.out.println("-------------------------------"); System.out.println("nina instanceof Cat = "+(nina instanceof Cat));//ture System.out.println("nina instanceof Animal = "+(nina instanceof Animal));//true //System.out.println("hasx instanceof Cat = "+(hasx instanceof Cat)); /* 这样编译错误:inconvertible types 使用instanceof 前提必须要有继承关系, */ System.out.println("-------------------------------"); System.out.println("hasx instanceof Dog = "+(hasx instanceof Dog));//true System.out.println("hasx instanceof Animal = "+(hasx instanceof Animal));//true //动物引用yoyo 判断关系 System.out.println("yoyo instanceof Animal = "+(yoyo instanceof Animal));//true System.out.println("yoyo instanceof Cat = "+(yoyo instanceof Cat));//false System.out.println("yoyo instanceof Dog = "+(yoyo instanceof Dog));//false System.out.println("coco instanceof Animal = "+(coco instanceof Animal));//true System.out.println("coco instanceof Cat = "+(coco instanceof Cat));//false System.out.println("coco instanceof Dog = "+(coco instanceof Dog));//false /*这行编译没错而且可以运行,因为引用类型coco是Animal,还是与Dog有继承关系*/ System.out.println("-------------------------------"); //向下转型, Cat my=(Cat)coco; //my引用类型是猫,猫的成员当然可以访问咯 System.out.println(my.eyesColor); my.miaow(); //调用Animal创建的方法,可扩展行增强了 System.out.println("-------------------------------"); coco.say(coco); coco.say(nina); coco.say(hasx); coco.say(yoyo); System.out.println("-------------------------------"); }
多态实例
经过上面对对象转型的认识,可以编写测试多态的代码
//一.多态测试 //多态三个条件:1.有继承 2.有重写 3.父类引用指向子类对象 package me.polymoph; //二.抽象方法就是用来重写的,1.继承下来的子类必须重写 2.抽象类不能不能new。3. //Final 1.Final的变量值不能改变 2.Final 的方法不能重写 3.Final的方法不能被继承 abstract class Animal{ //~ public void enjoy(){ //~ //动物高兴了叫 //~ System.out.println("我叫叫叫~~"); //~ } //抽象类改写 abstract void enjoy(); } //子类 class Dog extends Animal{ //狗高兴不一定叫,我狗跳墙,复写方法 public void enjoy(){ System.out.println("我狗跳墙"); } } class Cat extends Animal{ //猫高兴了,走猫步,复写方法 public void enjoy(){ System.out.println("我走猫步"); } } class Wolf extends Animal{ //狼高兴了,我吃兔子 public void enjoy(){ System.out.println("我吃兔子"); } } //然后测试类 public class Polymoph{ public static void main(String[] args){ //创建动物对象,超类引用,赋予之类对象 Animal coco=new Dog(); // coco.enjoy(); coco=new Cat(); coco.enjoy(); coco=new Wolf(); coco.enjoy(); /*输出: 我狗跳墙 我走猫步 我吃兔子 *///输出的是子类的方法 } }
作者:YangGan出处: http://blog.csdn.net/incyanggan本文基于 署名 2.5 中国大陆 许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名Yanggan (包含链接).