理论教育 Java程序设计:多态应用

Java程序设计:多态应用

时间:2023-10-18 理论教育 版权反馈
【摘要】:Example5_12.java在Example5_12.java文件中的CarFactory类中定义的方法produceCar()方法原型为:public static Car produceCar();,可以看出produceCar()方法的返回值类型为Car类型,而在produceCar()方法中生成的是各子类Bmw, Benz, Audi实体,但返回的是父类引用,即让父类引用指向子类对象,符合多态思想,如果还需要生产其他类型的汽车,则只需要定义该车的类从Car类继承,则可以生产相应的汽车,因此增强了程序的扩展性。

Java程序设计:多态应用

(1)多态作为形参,接受子类对象,避免函数重载过度使用,以增强程序的扩展性。

【例5.11】编写程序,输出任何几何图形的面积和周长

① 通过方法重载的方式进行实现。

定义Shap抽象类,Shap类中包含getArea()和getLength()两个抽象方法,让Circle类和Rectangle类继承Shap类,同时Circle类定义自己新增的属性半径radius和圆周率PI,Rectangle类新增自己的属性宽度width和长度length,再在Circle类和Rectangle类中重写Shap类中求面积和周长的方法,分别求圆形和方形的面积及周长。再定义一个ComputShapAreaLen类,在类中通过对printAreaandLen()方法进行传递圆形和方形的方式进行重载,以分别实现输出圆形和方形的面积及周长。再在测试类的主方法中定义ComputShapAreaLen类的对象调用printAreaandLen()分别求圆形和方形的面积及周长。Shap类,Circle类,Rectangle类,Comput ShapAreaLen类及测试类Example5_11都定义在同一个文件Example5_11.java中,具体代码如下:

Example5_11.java

在上述例子,只计算了圆形和方形两种图形的面积和周长,如果要再计算三角形、梯形或其他图形的面积和周长,则我们可以增加相应的形状类,但同时我们必须在ComputAreaandLen类中重载一个输出相应图形的面积及周长的printAreaandLen()方法,即对ComputAreaandLen类进行修改。这样做存在一个问题,就是当我们在ComputAreaandLen类中去重载printAreaandLen()方法时,有可能会误修改到ComputAreaandLen类中的其他方法,此操作不满足软件设计中的“开-闭”原则,即一个软件实体如类、模块应该对扩展开放,对修改关闭。接下来我们使用多态来解决重载所带来的问题。

② 多态作为形参用来满足“开-闭”原则。

多态的特点就是当父类引用指向子类对象后,父类引用可以调用子类中重写了父类中的非静态方法。因此,基于多态的特点我们可以在上面程序里的ComputAreaandLen类中,将printAreaandLen()方法的参数定义为Shap引用即可,Shap引用可以指向其子类对象,当Shap引用指向哪一个子类对象时,则Shap引用在调用getArea()和getLen()方法时,就调用的是那一个子类中重写到的非静态方法,从而实现输出各类图形的面积和周长要求。因此,我们只需要对例5.11中的ComputAreandLen中的printAreaandLen()方法去掉方法重载,保留一个方法,并将printAreaandLen()方法的参数设置成Shap类的引用即可。对例5.11中的ComputAreaandLen类进行修改如下。

通过使用多态来实现上述程序,可以减少方法的重载,并且可以满足软件设计中的“开-闭”原则,即如果在例5.11中还要输出梯形、三角形及其他图的面积及周长时,我们只需要定义相关的图形类,再直接在主方法中进行测试即可,而不需要去修改ComputShapAreaLen类。因此,多态可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

(2)多态可以作为返回值类型。

【例5.12】本例通过多态作为返回值类型,来获取任意类型的车对象。定义汽车类Car,成员变量有:名字和颜色,成员方法有:参构造函数及run方法。分别定义Bmw类、Benz类、Audi类继承自Car类,在各个类中定义有参构造方法,并用super关键字实现对父类Car类中的名字和颜色进行初始化。定义CarFactory类,在类中定义produceCar()静态方法,随机生产各类汽车,并将生产的汽车对象使用父类引用即使用多态返回值进行返回。注:Car, Bmw,Benz, Audi,CarFactory及测试类Example5_12类在此处均定义在同一个文件Example5_12.java中,也可以分别定义在各个以类命名的java文件中。

在produceCar()方法中使用(int)Math.round(Math.random()*2); 生成0~2之间的随机整数。

Example5_12.java

在Example5_12.java文件中的CarFactory类中定义的方法produceCar()方法原型为:public static Car produceCar();,可以看出produceCar()方法的返回值类型为Car类型,而在produceCar()方法中生成的是各子类Bmw, Benz, Audi实体,但返回的是父类引用,即让父类引用指向子类对象,符合多态思想,如果还需要生产其他类型的汽车(如法拉利车),则只需要定义该车的类从Car类继承,则可以生产相应的汽车,因此增强了程序的扩展性。

(3)多态之类型转型。

① 基本类型转换:在类型兼容的情况下,如int, float, double数值型基本类型存在类型兼容,低类型向高类型转换时,在赋值时自动转换,高类型向低类型转换时,在赋值时需要强制转换。

② 类类型转换:类类型间能转换的前提是必须存在继承关系,若不存在继承关系且不存在多态,则进行了类类型转换,即使编译没错,运行时也会报错。子类对象转父类对象自动转换,父类对象转子类对象,需要类类型转换。如Dog类是Animal类的子类,则有:

Animal animal=new Dog();

Dog dog=(Dog)animal; dog.run();

【例5.13】在Example5_13.java中定义Animal类,Animal类中有eat()和cry()方法;定义Dog类继承Animal类,在Dog类中重写Animal类中的eat(),新增加lookHome()方法。再在主类Example5_13的主方法中用父类引用指向子类对象:Animal animal = new Dog();,则下列语句是否存在编译错误,若没错则调用的父类中还是子类中的方法呢?

① animal.eat();

② animal.cry();

③ animal.lookHome();

Example5_13.java

(4)多态与非多态下的类类型转换。

以例5.13中所定义的Animal类,Dog类,Fish类为例说明类类型转换的相关知识。(www.daowen.com)

① 多态下的类类型转换。

在Example5_13.java程序中如有:

Animal animal=new Dog();

若用父类引用animal调用Dog类中特有的方法lookHome(),会出现编译错误,因为父类引用只能调用父类中的成员,此时可用类类型的强制类型转换来实现。

Dog dog=(Dog)animal;

转换后就能调用子类中的新增成员,如:

dog.lookHome();

② 非多态下的类类型转换。

若有:Animal animal=new Animal();

再通过类类型转换,如:

Dog dog=(Dog) animal;

dog.lookHome();

虽然编译能通过,但运行时将会出现ClassCastException异常。

③ 多态下的兄弟类类型转换。

若有:Animal animal=new Dog();

再将animal指向的Dog对象采用类类型转换为Fish对象,如:

Fish fish=(Fish)animal;

fish.swim();

虽然编译能通过,但运行时将会出现ClassCastException异常。

从③可以看出虽然是多态,但狗不能转为鱼,因为它们之间没有继承关系。因此在Java中,若要实现类类型转换,则必须存在继承关系,并且是在多态的状态下,若不存在继承关系或不是多态的状态,进行了类类型转换,即便是编译没错,但运行时也会报错。

(5)多态下调用子类中新增加的特有方法。

我们知道通过使用多态可以使程序的扩展性更强,但多态的弊端是父类引用只能指向父类成员,因此无法引用到在子类中的新增成员,为了解决能在多态的状态下引用子类的新增成员方法的问题,可以使用instanceof 关键字,判断具体是哪一个子类对象,再进行类类型转换,从而可以执行该子类中新增的特有方法。

【例5.14】多态下类类型转换的应用—— 多态下调用子类中新增加的特有方法。在主类中定义runSubclassMethod(Animal animal)方法,参数animal接收动物对象,根据传入的具体动物,执行该动物特有的方法。由于方法参数使用多态,因此不能确定传入的是哪种动物,runSubclassMethod方法中使用instanceof 关键字进行判断具体是何种动物,进行类类型转换后,再执行该动物的特有方法。

Example5_14.java

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈