多态性
多态是在继承性的继承上扩展的概念。可以实现父子相关转换的处理
两种实现模式:
方法的多态性
对象的多态性
(一)方法的多态性
1、方法的重载:同一个方法名称可以根据传入参数的类型或个数的不同实现不同的功能。
2、方法的覆写:同一个方法可能因为子类的不同有不同的实现。
(二)对象的多态性:父子实例间的转换处理,有两种模式:
1、对象的向上转型
父类 父类实例 = 子类实例 自动完成转型
2、对象的向下转型
子类 子类实例 = (子类)父类实例 强制完成转换
从实际的转型处理来讲,大部分情况下考虑的最多的是对象的向上转型。对于对象的向下转型,往往都是在使用子类的特殊功能(子类可以对谷类进行功能扩充)的时候要采用向下转型。还有一些时候是不会考虑转型的(String类)。
对象向上转型(接收或返回参数的统一性)
范例:观察一个简单代码
package 面向对象;
class Message {
public void print() {
System.out.println("www.mldn.cn");
}
}
class DataBaseMessage extends Message {
public void print() {
System.out.println("Oracle数据库连接信息....");
}
}
public class DuotaiDemo00 {
public static void main(String[] args) {
DataBaseMessage msg = new DataBaseMessage();
msg.print();
}
}
输出结果:
Oracle数据库连接信息....
本程序由于实例化的是子类对象,并且子类覆写了父类中的print()方法,所以调用的是被覆写的方法。
范例:观察向上转型
package 面向对象;
class Message {
public void print() {
System.out.println("www.mldn.cn");
}
}
class DataBaseMessage extends Message {
public void print() {
System.out.println("Oracle数据库连接信息....");
}
}
public class DuotaiDemo00 {
public static void main(String[] args) {
Message msg = new DataBaseMessage(); //向上转型
msg.print();
}
}
输出结果:
Oracle数据库连接信息....
Message msg = new DataBaseMessage(); //向上转型
主要看new后面的类是谁,以及该实例化的子类是否进行了方法覆写。
这时向上转型的操作的主要用处:
范例:向上转型的优势
package 面向对象;
class Message {
public void print() {
System.out.println("www.mldn.cn");
}
}
class DataBaseMessage extends Message {
public void print() {
System.out.println("Oracle数据库连接信息....");
}
}
class WebServerMessage extends Message {
public void print() {
System.out.println("服务器连接信息....");
}
}
public class DuotaiDemo00 {
public static void main(String[] args) {
fun(new DataBaseMessage()); //Message msg = new DataBaseMessage();
fun(new WebServerMessage()); //Message msg = new WebServerMessage();
}
public static void fun(Message msg) { //不管现在传递的是哪一个子类,都可以用一个参数来接收
msg.print();
}
}
输出结果:
Oracle数据库连接信息....
服务器连接信息....
转型的主要特点在于,可以对参数进行统一的设计,这样便于维护。
对象向下转型:
向下转型的主要特点在于需要使用一些子类自己特殊的定义处理。
范例:实现向下转型
package 面向对象;
class Person01 {
public void print() {
System.out.println("一个正常的人类行为,吃饭、睡觉、繁衍。");
}
}
class SuperMan extends Person01 {
public String fly() {
return "我可以飞。";
}
public String fire() {
return "我可以喷火";
}
}
public class DuotaiDemo01 {
public static void main(String[] args) {
System.out.println("------正常状态下的超人应该是一个普通人的状态----");
Person01 per = new SuperMan(); //向上转型
per.print();
System.out.println("------外星怪兽狗骚扰地球,准备消灭人类。。。");
SuperMan man = (SuperMan) per; //向下转型
System.out.println(man.fly());
System.out.println(man.fire());
}
}
输出结果:
------正常状态下的超人应该是一个普通人的状态----
一个正常的人类行为,吃饭、睡觉、繁衍。
------外星怪兽狗骚扰地球,准备消灭人类。。。
我可以飞。
我可以喷火
向上描述的是公共特征,向下描述的是子类自己特色的定义环境。但是需要明确的是,向下转型并不是一件安全的事情。因为在进行向下转型前一定要首先发生向上转型。
范例:观察错误的程序
package 面向对象;
class Person01 {
public void print() {
System.out.println("一个正常的人类行为,吃饭、睡觉、繁衍。");
}
}
class SuperMan extends Person01 {
public String fly() {
return "我可以飞。";
}
public String fire() {
return "我可以喷火";
}
}
public class DuotaiDemo01 {
public static void main(String[] args) {
System.out.println("------正常状态下的超人应该是一个普通人的状态----");
Person01 per = new Person01(); //向上转型
per.print();
System.out.println("------外星怪兽狗骚扰地球,准备消灭人类。。。");
SuperMan man = (SuperMan) per; //向下转型
}
}
输出结果:
------正常状态下的超人应该是一个普通人的状态----
一个正常的人类行为,吃饭、睡觉、繁衍。
------外星怪兽狗骚扰地球,准备消灭人类。。。
Exception in thread "main" java.lang.ClassCastException: 面向对象.Person01 cannot be cast to 面向对象.SuperMan
at 面向对象.DuotaiDemo01.main(DuotaiDemo01.java:
以后只要是发生对象的向下转型之前,一定要首先发生向上转型,两个没用任何关系的实例如果要进行强制转换,就会出现“ClassCastException”异常,所以向下转型并不是一件安全的事情。
instanceof 关键字的应用
向下转型是一件存在安全隐患的操作,为了保证向下转型的正确性,往往需要在转型前进行判断,判断某个实例是否是某个类的对象,这个就需要通过instanceof语法实现
对象instanceof类
该判断将返回一个boolean类型,如果是true表示实例是指定类对象
范例:观察instanceof的使用
package 面向对象;
class Person01 {
public void print() {
System.out.println("一个正常的人类行为,吃饭、睡觉、繁衍。");
}
}
class SuperMan extends Person01 {
public String fly() {
return "我可以飞。";
}
public String fire() {
return "我可以喷火";
}
}
public class DuotaiDemo01 {
public static void main(String[] args) {
Person01 per = new Person01(); //不转型
System.out.println(per instanceof Person01); //true
System.out.println(per instanceof SuperMan); //false
}
}
范例:观察instanceof关键字
package 面向对象;
class Person01 {
public void print() {
System.out.println("一个正常的人类行为,吃饭、睡觉、繁衍。");
}
}
class SuperMan extends Person01 {
public String fly() {
return "我可以飞。";
}
public String fire() {
return "我可以喷火";
}
}
public class DuotaiDemo01 {
public static void main(String[] args) {
Person01 per = new SuperMan(); //不转型
System.out.println(per instanceof Person01); //true
System.out.println(per instanceof SuperMan); //true
}
}
所以在以后的开发中如果要执行对象的向下转型,最好先判断一次。
如下:作出判断
package 面向对象;
class Person01 {
public void print() {
System.out.println("一个正常的人类行为,吃饭、睡觉、繁衍。");
}
}
class SuperMan extends Person01 {
public String fly() {
return "我可以飞。";
}
public String fire() {
return "我可以喷火";
}
}
public class DuotaiDemo01 {
public static void main(String[] args) {
Person01 per = new SuperMan(); //向上转型
if (per instanceof SuperMan) {
SuperMan man = (SuperMan)per;
System.out.println(man.fly());
System.out.println(man.fire());
}
}
}
在以后进行完善性程序开发过程中,在转型前一定要使用instanceof进行判断.