多态
1.运行下面代码,回答问题
(1)源代码
public class ParentChildTest {
public static void main(String[] args) {
Parent parent=new Parent();
parent.printValue();
Child child=new Child();
child.printValue();
parent=child;
parent.printValue();
parent.myValue++;
parent.printValue();
((Child)parent).myValue++;
parent.printValue();
}
}
class Parent{
public int myValue=100;
public void printValue() {
System.out.println("Parent.printValue(),myValue="+myValue);
}
}
class Child extends Parent{
public int myValue=200;
public void printValue() {
System.out.println("Child.printValue(),myValue="+myValue);
}
}
(2)问题
程序运行的结果:
解释:首先定义Parent类的变量,会调用Parent类的printValue函数,此时myValue=100;第二个定义了Child一个类,所以会调用child的函数,myValue=200;第三个让parent=child,这样就会调用child的函数,myValue=200;第四个parent.myValue++,会在myValue上加一,但是parent=child仍然成立,所以还是会调用child的函数,myValue=200;最后一个强制转换,所以加1之后myValue也会变化,还会继续调用child的函数。
总结:
当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。这也就会用到多态性。
如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。
如果子类被当作父类使用,则通过子类访问的字段是父类的!
2.多态的含义与用途(动物园)
Zoo1:
package zoo1;
public class Zoo
{ public static void main(String args[])
{
Feeder f = new Feeder("小李");
// 饲养员小李喂养一只狮子
f.feedLion(new Lion());
// 饲养员小李喂养十只猴子
for (int i = 0; i < 10; i++)
{
f.feedMonkey(new Monkey());
}
// 饲养员小李喂养5只鸽子
for (int i = 0; i < 5; i++)
{
f.feedPigeon(new Pigeon());
}
}
}
class Feeder
{
public String name;
public Feeder(String name)
{
this.name = name;
}
public void feedLion(Lion l)
{
l.eat();
}
public void feedPigeon(Pigeon p)
{
p.eat();
}
public void feedMonkey(Monkey m)
{
m.eat();
}
}
class Lion
{
public void eat()
{
System.out.println("我不吃肉谁敢吃肉!");
}
}
class Monkey
{
public void eat()
{
System.out.println("我什么都吃,尤其喜欢香蕉。");
}
}class Pigeon
{
public void eat()
{
System.out.println("我要减肥,所以每天只吃一点大米。");
}
}
缺点:要多次循环,每个类中都有相同的函数,但是没有任何联系,如果要增加一个要求,要多次修改。
Zoo2:
Feeder类的三个喂养方法现在可以合并为一个feedAnimal()方法,注意它接收一个类型为Animal参数,而不是三个具体的动物类型。依据多态特性,此方法将可以接收任何一个派生自Animal类的子类对象
先定义一个Feeder类,定义animal类,其中有一个eat方法,只有函数名,没有函数内容。其他三个类继承这个类方法,定义适合自己的方法,覆盖;这是抽象类。
Zoo3:
修改feedAnimals方法,让它接收一个Animal数组,现在只需要一句代码,就可以模拟出喂养一批各种各样的动物的过程
Zoo4:
package zoo4;
import java.util.Vector;
public class Zoo {
public static void main(String args[]) {
Feeder f = new Feeder("小李");
Vector<Animal> ans = new Vector<Animal>();
//饲养员小李喂养一只狮子
ans.add(new Lion());
//饲养员小李喂养十只猴子
for (int i = 0; i < 10; i++) {
ans.add(new Monkey());
}
//饲养员小李喂养5只鸽子
for (int i = 0; i < 5; i++) {
ans.add(new Pigeon());
}
f.feedAnimals(ans);
}
}
class Feeder {
public String name;
Feeder(String name) {
this.name = name;
}
public void feedAnimals(Vector<Animal> ans) {
for (Animal an : ans) {
an.eat();
}
}
}
abstract class Animal {
public abstract void eat();
}
class Lion extends Animal {
public void eat() {
System.out.println("我不吃肉谁敢吃肉!");
}
}
class Monkey extends Animal {
public void eat() {
System.out.println("我什么都吃,尤其喜欢香蕉。");
}
}
class Pigeon extends Animal {
public void eat() {
System.out.println("我要减肥,所以每天只吃一点大米。");
}
}
第二次重构之后,Feeder类的feedAnimals()方法接收的是一个Animal数组,这有一个限制,就是只能创建固定个数的数组,无法动态地增减动物个数。修改feedAnimals方法,让其接收一个元素数目可变的对象容器,利用Vector<T>,Vector<T>是JDK中提供的一个对象集合,可以随时向其中加入或移除对象。
总结:
应用多态,可以使我们的代码具有更强的适用性。当需求变化时,多态特性可以帮助我们将需要改动的地方减少到最低限度。使用多态好处:当要修改程序并扩充系统时,你需要修改的地方较少,对其它部分代码的影响较小
3. 用多态的方法模拟ATM操作流程。
(1)源代码
import java.util.Scanner;
/*
* ATM机取款
*/
//陈晓阳 20153253
public class Money1 {//执行类
public static void main(String args[])
{
System.out.println("请插卡!");
System.out.println("请选择语言:");
int i1;
Scanner inm=new Scanner (System.in);
i1=inm.nextInt();
if(i1==1)//英语
{System.out.println("英语");}
if(i1==2)//汉语
{System.out.println("汉语");}
Account ac=new Account("12345678901","zhangsan","2016/11/15","098765",6000);
String i1m;//密码
System.out.println("请输入密码:");
Scanner inmm=new Scanner (System.in);
i1m=inmm.next();
while(i1m.equals(ac.mima))
{System.out.println("请选择操作数:1 取款 2 存款 3 转账 4 退卡");
int i;
Scanner in=new Scanner (System.in);
i=in.nextInt();
switch(i)
{
case 1:
//System.out.println("请输入密码:");
String aa;
Scanner in1=new Scanner (System.in);
aa=in.nextLine();
ac.withdraw();
break;
case 2://存款
ac.cunqian();
break;
case 3://转账
ac.zhuanzhang();
break;
case 4:
System.out.println("退卡");break;
default :
break;
}
}
}
}
abstract class ATM//定义抽象类
{
public abstract void withdraw();
public abstract void cunqian();
public abstract void zhuanzhang();
}
class Account extends ATM//
{
String num;//长度11位
String name;
String Date;
String mima;
//int chaozuo[]={1,2,3,4,5};
double yue;//
Account(String n,String na,String d,String m,double y)
{
num=n;name=na;Date=d;mima=m;yue=y;
}
public void withdraw()//取款
{
System.out.println("请选择取款金额!100元、500元、1000元、1500元、2000元、5000元、其他金额");
int a;
Scanner in2=new Scanner (System.in);
a=in2.nextInt();
if(yue>a){yue=yue-a;System.out.println("余额"+yue);}
else System.out.println("余额不足!");
}
public void cunqian()//存款
{
System.out.println("请输入存款金额!");
int a1;
Scanner a11=new Scanner (System.in);
a1=a11.nextInt();
yue=yue+a1;
System.out.println("余额"+yue);
}
public void zhuanzhang()//转账
{
System.out.println("请输入转账卡号");
String a2;
Scanner a12=new Scanner (System.in);
a2=a12.nextLine();
System.out.println("请输入转账的金额:");
int a3;
Scanner a13=new Scanner (System.in);
a3=a13.nextInt();
if(yue>a3)
{yue=yue-a3;System.out.println("余额"+yue);System.out.println("转账成功!");}
else System.out.println("余额不足!");
}
}
(3)先定义一个抽象类,在类中写上函数名,没有函数体,再定义一个类,继承抽象类,函数中有要有抽象类中的所有函数,并定义为public类型的,在主函数中调用这些函数。