[2014-3-14]JAVA笔记_多态(Polymophism)、instanceof关键字

来源:互联网 发布:it培训机构 知乎 编辑:程序博客网 时间:2024/06/02 03:47

一、什么是多态?

         Polymorphism means “different forms.” In object-oriented programming, you have the same interface from the base class, and different forms using that interface: the different versions of the dynamically bound methods. (摘自thinking in java, Page217)  polymorphism (also called dynamic bindingor late bindingor run-time binding)

例子:多态,子类-->父类  向上转型

public class PolyTest{public static void main(String[] args){//Parent parent = new Parent();//parent.sing();//Child child = new Child();//child.sing();Parent p = new Child();//子类即父类p.sing();}}class Parent{public void sing(){System.out.println("parent is singing");}}class Child extends Parent{//public void sing(int i)//重载public void sing(){System.out.println("child is singing");}}//Note:当申明父类型的引用去指向字类型的对象时,父类调用方法原则:第一,会去//父类中查看是否有此方法,如果有继续查找此方法是否有被子类继承,如果继承//则继续查找此方法是否覆写,如果覆写则调用覆写的方法,如果没有被覆写则直接//调用父类中的方法。第二,如果父类型的引用调用方法时此方法在父类中没有定义,则直接会报错,因为什么类型的引用就能调用什么类型的方法。//(与重载无关,如果子类重载了父类的方法,调用时任然是调用父类的方法,如果有//被覆写则调用覆写的方法)

为什么要向上转型?

 a) 可以保持父类不需要修改,只需要子类继承父类,然后覆写父类的方法。

 b)可以用父类型引用,接受子类型引用参数,这样父类方法不需要改变,只需要增加子类即可。(详见第二十讲最后大约10分钟)

public class PolyTest5{/*public void runCar(BMW bmw)//不使用多态:子类添加,方法也必须添加。{bmw.run();}public void runCar(QQ qq)//传的都是具体的车的类型。QQ不能接受BMW{qq.run();}*///使用多态:无论子类增加多少类,父类方法不需要修改public void runCar(Car car)//可接受car类型和car的子类类型{car.run();}public static void main(String[] args){/* PolyTest5 test = new PolyTest5();BMW bmw = new BMW();test.runCar(bmw);QQ qq = new QQ();test.runCar(qq);*/PolyTest5 test = new PolyTest5();Car car = new BMW();//通过多态自动向上转换实现test.runCar(car);QQ qq = new QQ();test.runCar(qq);//子类引用传递给父类方法接受。向上类型转换}}class Car{public void run(){System.out.println("car is running");}}class BMW extends Car{public void run(){System.out.println("BMW is running");}}class QQ extends Car{public void run(){System.out.println("QQ is running");}}//总结:多态屏蔽掉了子类之间的差异性,用一个公共父类方法标识我的接口(方法的参数)//不管子类怎么改变,只要增加的子类都继承了这个父类,都可以作为参数传递到我的这个//方法里。



多态的晚绑定:

//验证晚绑定public class PolyTest4{public static void main(String[] args){A a = null;if(args[0].equals("1")){a = new B();}else if(args[0].equals("2")){a = new C();}else if(args[0].equals("3")){a = new D();}a.method();}}class A{public void method(){System.out.println("A");}}class B extends A{public void method(){System.out.println("B");}}class C extends A{public void method(){System.out.println("C");}}class D extends A{public void method(){System.out.println("D");}}

向下转型:

例子:多态,父类-->子类, 向下转型

public class PolyTest2{public static  void main(String[] args){/*Animal animal = new Cat();Animal animal2 = new Animal();animal2 = animal;animal2.sing();*//*Animal animal = new Cat();Animal animal2 = new Animal();animal = animal2;animal.sing();*//*Cat cat = new Cat();Animal animal = cat;animal.sing();*/Animal animal = new Animal();Cat cat =new Animal();/*//向上类型转换Cat cat = new Cat();Animal animal = cat;animal.sing();//向下类型转换Animal a = new Cat();Cat c = (Cat)a;//向下转换的原则是:a实际指向的是什么,就可以把它转换成什么类型的引用c.sing();*/}}class Animal{public void sing(){System.out.println("animal is singing");}}class Dog extends Animal{public void sing(){System.out.println("dog is singing");}}class Cat extends Animal{public void sing(){System.out.println("cat is singing");}}

为什么要使用向下转换?

例子:

public class PolyTest3{public static void main(String[] args){//Fruit f = new Pear();//f.run();//Pear p = (Pear)f;//p.run();//Fruit f = new Pear();//f.grow();Fruit f = new Pear();Pear p = (Pear)f;p.grow();}}class Fruit{public void run(){System.out.println("fruit is running");}}class Pear extends Fruit{public void run(){System.out.println("pear is running");}public void grow(){System.out.println("pear is growing");}}

总结:子类里面新增了自己的方法时,父类引用需要调用子类方法此时就需要向下转型。将父类引用类型转型为子类引用类型,因为什么类型的引用就能指向什么类型的对象。





1. JAVA中面向对象主要有两种提现:

(1) 方法的重载与覆写。

(2) 对象的多态性。

对象的多态性主要分为以下两种类型:

(1) 向上转型:子类对象——>父类对象。

(2) 向下转型: 父类对象——>子类对象。

对于向上转型,程序会自动完成,而对于向下转型时,必须明确地指明要转型的子类类型。

【格式 对象转型】

对象向上转型: 父类 父类对象 = 子类实例;

对象向下转型: 子类 子类对象 = (子类)父类实例;

范例:对象的向上转型

//对象的向上转型class A{//定义类Apublic void fun1(){System.out.println("A --> public void fun1(){}");}public void fun2(){this.fun1();}};class B extends A{//子类通过extends继承父类public void fun1(){//覆写父类中的fun1()方法System.out.println("B --> public void fun1(){}");}public void fun3(){//子类自己定义的方法System.out.println("B --> public void fun3()");}};public class PolDemo01{public static void main(String []args){B b = new B();//定义子类实例化对象A a = b;//发生了向上转型的关系,子类 --> 父类a.fun1();//此方法被子类覆写过}}//总结:如果对象发生了向上转型关系后,所调用的方法一定是被子类覆写过的方法。
程序运行结果:

B --> public void fun1(){}


此时的对象a是无法调用B类中的fun3()方法的,因为此方法只在子类定义,而没有在父类中定义,如果想要调用子类自己的方法,则肯定要使用子类实例,所以此时可以将对象进行向下转型。

//对象的向下转型class A{//定义类Apublic void fun1(){System.out.println("A --> public void fun1(){}");}public void fun2(){this.fun1();}};class B extends A{//子类通过extends继承父类public void fun1(){//覆写父类中的fun1()方法System.out.println("B --> public void fun1(){}");}public void fun3(){//子类自己定义的方法System.out.println("B --> public void fun3(){}");}};public class PolDemo02{public static void main(String []args){A a = new B();//发生了向上转型的关系,子类-->父类B b = (B)a;//此时发生了向下转型关系b.fun1();//调用方法被覆写的方法b.fun2();//调用父类的方法b.fun3();//调用子类自己定义的方法}}

程序运行结果:

B --> public void fun1(){}
B --> public void fun1(){}
B --> public void fun3(){}

总结:如果想要调用子类自己的方法,则一定只能用子类声明对象,另外,在子类中调用了父类中的fun2()方法,fun2()方法要调用fun1()方法,但此时fun1()方法已经被子类所覆写,所以,此时调用的方法是被子类覆写过的方法。


注意: 对象向下转型的要求

在进行对象的向下转型前,必须首先发生对象向上转型,否则将出现对象转换异常

//错误的转型class A{//定义类Apublic void fun1(){System.out.println("A --> public void fun1(){}");}public void fun2(){this.fun1();}};class B extends A{//子类通过extends继承父类public void fun1(){//覆写父类中的fun1()方法System.out.println("B --> public void fun1(){}");}public void fun3(){//子类自己定义的方法System.out.println("B --> public void fun3(){}");}};public class PolDemo03{public static void main(String []args){A a = new A();//此时声明的是父类对象。父对象并不知道谁是子对象B b = (B)a;//此时发生了向下转型关系b.fun1();//调用方法被覆写的方法b.fun2();//调用父类的方法b.fun3();//调用子类自己定义的方法}}
由以上程序可以发现,此时的A类对象是由A类本身进行实例化的,然后将A类的实例化对象强制转换为子对象,这样写在语法上是没有任何错误的,但是在运行时出现了异常,因为此时父类用其本身类实例化自己的对象,但它并不知道谁是自己的子类,那肯定在转换时会出现错误。只需要将连个对象建立好关系即可解决此我呢提,在声明父类对象时发生向上转型关系“A a = new B();”,这时相当于是由子类去实例化父类对象,也就是说这时父类知道有这么一个子类,所以下面在进行转换时就不会再有问题。


2. instanceof 关键字:判断某个对象是否是某个类的实例。

语法形式: 引用名  instanceof  类名(接口名),返回 boolean  值。


//Instanceof 关键字作用public class InstanceofTest{public static void main(String args[]){People people = new Man();System.out.println(people instanceof People);//因为 Man 是 People 的子类,根据继承,子类就是父类,//因此 Man 也可以看作是 People 的实例。}}class People{};class Man extends People{};


//使用instanceof判断一个对象属于那个类的实例class A{//定义类Apublic void fun1(){System.out.println("A --> public void fun1(){}");}public void fun2(){this.fun1();}};class B extends A{//子类通过extends继承父类public void fun1(){//覆写父类中的fun1()方法System.out.println("B --> public void fun1(){}");}public void fun3(){//子类自己定义的方法System.out.println("B --> public void fun3(){}");}};public class InstanceofDemo01{public static void main(String []args){A a1 = new B();//通过向上转型实例化A类对象System.out.println("A a1 = new B():" + (a1 instanceof A));System.out.println("A a1 = new B():" + (a1 instanceof B));A a2 = new A();//通过A类的构造实例化本类对象System.out.println("A a2 = new A():" + (a2 instanceof A));System.out.println("A a2 = new A():" + (a2 instanceof B));}}//通过子类实例化的对象同时是子类和父类的实例
程序运行结果:

A a1 = new B():true
A a1 = new B():true
A a2 = new A():true
A a2 = new A():false

//在向下转型前进行验证class A{//定义类Apublic void fun1(){System.out.println("A --> public void fun1(){}");}public void fun2(){this.fun1();}};class B extends A{//子类通过extends继承父类public void fun1(){//覆写父类中的fun1()方法System.out.println("B --> public void fun1(){}");}public void fun3(){//子类自己定义的方法System.out.println("B --> public void fun3(){}");}};class C extends A{//子类通过extends继承父类public void fun1(){//覆写父类中的fun1()方法System.out.println("C --> public void fun1(){}");}public void fun5(){//子类自己定义的方法System.out.println("C --> public void fun3(){}");}};public class InstanceofDemo02{public static void main(String []args){fun(new B());//传递B类实例,产生向上转型fun(new C());//传递C类实例,产生向上转型}public static void fun(A a){//此方法可以分别调用各自子类单独定义的方法a.fun1();if(a instanceof B){//判断是否是B类实例B b = (B)a;//进行向下转型b.fun3();//调用子类自己定义的方法}if(a instanceof C){//判断是否是C类实例C c = (C)a;//进行向下转型c.fun5();//调用子类自己定义的方法}}}
程序运行结果:

B --> public void fun1(){}
B --> public void fun3(){}
C --> public void fun1(){}
C --> public void fun3(){}





1 0
原创粉丝点击