[2014-3-14]JAVA笔记_多态(Polymophism)、instanceof关键字
2014-03-14 14:26
309 查看
一、什么是多态?
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)
例子:多态,子类-->父类 向上转型
为什么要向上转型?
a) 可以保持父类不需要修改,只需要子类继承父类,然后覆写父类的方法。
b)可以用父类型引用,接受子类型引用参数,这样父类方法不需要改变,只需要增加子类即可。(详见第二十讲最后大约10分钟)
多态的晚绑定:
向下转型:
例子:多态,父类-->子类, 向下转型
为什么要使用向下转换?
例子:
总结:子类里面新增了自己的方法时,父类引用需要调用子类方法此时就需要向下转型。将父类引用类型转型为子类引用类型,因为什么类型的引用就能指向什么类型的对象。
1. JAVA中面向对象主要有两种提现:
(1) 方法的重载与覆写。
(2) 对象的多态性。
对象的多态性主要分为以下两种类型:
(1) 向上转型:子类对象——>父类对象。
(2) 向下转型: 父类对象——>子类对象。
对于向上转型,程序会自动完成,而对于向下转型时,必须明确地指明要转型的子类类型。
【格式
对象转型】
对象向上转型:
父类 父类对象 = 子类实例;
对象向下转型:
子类 子类对象 = (子类)父类实例;
范例:对象的向上转型
B --> public void fun1(){}
此时的对象a是无法调用B类中的fun3()方法的,因为此方法只在子类定义,而没有在父类中定义,如果想要调用子类自己的方法,则肯定要使用子类实例,所以此时可以将对象进行向下转型。
程序运行结果:
B --> public void fun1(){}
B --> public void fun1(){}
B --> public void fun3(){}
总结:如果想要调用子类自己的方法,则一定只能用子类声明对象,另外,在子类中调用了父类中的fun2()方法,fun2()方法要调用fun1()方法,但此时fun1()方法已经被子类所覆写,所以,此时调用的方法是被子类覆写过的方法。
注意: 对象向下转型的要求
在进行对象的向下转型前,必须首先发生对象向上转型,否则将出现对象转换异常
2. instanceof 关键字:判断某个对象是否是某个类的实例。
语法形式: 引用名 instanceof 类名(接口名),返回 boolean 值。
A a1 = new B():true
A a1 = new B():true
A a2 = new A():true
A a2 = new A():false
B --> public void fun1(){}
B --> public void fun3(){}
C --> public void fun1(){}
C --> public void fun3(){}
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{ //定义类A public 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{ //定义类A public 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{ //定义类A public 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{ //定义类A public 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{ //定义类A public 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(){}
相关文章推荐
- 黑马程序员-java多态学习笔记
- Java笔记----5. 面向对象(封装、继承、多态)
- Java 回顾笔记7_多态
- 《Java 编程思想》第8章 多态 笔记
- 面向对象三大特征之多态——Java笔记(七)
- java笔记-面向对象-多态
- Java学习笔记(4): 继承与多态
- 学习笔记 Java_ch03_多态_抽象类_最终类_ch04_接口 2014.7.26
- java笔记之封装、继承、重写、多态以及类型转换
- [Java][视频] 笔记-对象转型 和 动态绑定(多态)
- Java 基础一些代码练习笔记(多态2)
- Java学习笔记----多态
- java 从零开始,学习笔记之基础入门<抽象类_接口_多态>(十三)
- JAVA随堂笔记课【九】:多态、抽象
- 学习Java.对于继承和多态的随堂笔记
- Java学习笔记---继承和多态
- java自学笔记之面向对象多态
- Java学习笔记之多态
- java学习笔记------继承和多态 覆盖
- 笔记——Java面向对象之多态