多态

下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么?

        m=d;

         d=m;

          d=(Dog)m;

          d=c;

          c=(Cat)m;

     结论:

     java中基类对象不能当做子类对象使用,需要用强制转换来实现,子类对象变量=(子类名)基类对象名;错误的代码是d=m; d=c;

1.   左边的程序运行结果是什么?

2.   你如何解释会得到这样的输出?
3.   计算机是不会出错的,之所以得到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪些语法特性?

运行结果截图:

 

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++;

System.out.println(parent.myValue);

System.out.println(child.myValue);

parent.printValue();

 

/*((Child)parent).myValue++;

System.out.println(parent.myValue);

System.out.println(child.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);

}

}

 

   结论:

当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的真实类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。
这个特性实际上就是面向对象多态特性的具体表现。

如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。
如果子类被当作父类使用,则通过子类访问的字段是父类的!

第一个value调用的是父类的方法,输出值为100

第二个value调用的是子类的方法,输出值为200

第三个中子类赋值给父类,因此调用了子类的方法,输出值为200

第四个中调用了子类的构造方法,但是value值为100,所以没有影响

第五个中调用的是子类的方法,value的值也是子类的

 

  请使用javap查看编译器为TestPolymorphism.java生成的字节码指令,然后通过互联网搜索资料,尝试从底层开始理解Java编译器是如何为多态代码生成字节码指令,在程序运行过程中,多态特性又是如何实现的。

class Parent

{

public int value=100;

public void Introduce()
{

System.out.println("I'm father");

}


}

class Son extends Parent
{

public int value=101;

public void Introduce()
{

System.out.println("I'm son");

}

}


class Daughter extends Parent
{

public int value=102;
public void Introduce()
{

System.out.println("I'm daughter");

}

}

public class TestPolymorphism
{


public static void main(String args[])
{

Parent p=new Parent();

p.Introduce();

System.out.println(p.value);

p=new Son();

p.Introduce();

System.out.println(p.value);

p=new Daughter();

p.Introduce();

System.out.println(p.value);


}


}

结果:

I'm father
100
I'm son
100
I'm daughter
100

 

多态依赖于类型和实现的分离,多用来把接口和实现分离。

 

用多态的方法模拟ATM操作流程。

 

package dome;//2016.11.18    20153314    严鹏    多态法import java.util.*;public class S2{

public static void main(String[] args) {

@SuppressWarnings("resource")

Scanner in=new Scanner(System.in);

ATM atm=new ATM();int choose=0,num=0,p2=1;

String pw;

System.out.println("输入账户密码:");

pw=in.next();if(atm.ifPass(pw)){while(p2==1){

    

    System.out.println("********************");

    System.out.println(" 1.存款:");

    System.out.println(" 2.取款:");

    System.out.println(" 3.转账汇款:");

    System.out.println(" 4.修改密码:");

    System.out.println(" 5.查询余额:");

    System.out.println(" 6.退卡:");

    System.out.println("********************");

    System.out.println("请选择:");

choose=in.nextInt();switch(choose){case 1:

System.out.println("输入存款金额:");

num=in.nextInt();

atm.save(num);

System.out.println("存款成功!");

System.out.println("当前余额:"+atm.getRest()+"");break;case 2:

System.out.println("请选择:");int a[]={100,500,1000,1500,2000,5000};for(int i=0;i<a.length;i++)

System.out.println((i+1)+"."+a[i]+"");

System.out.println("7.其他");int ch=in.nextInt();if(ch>=1&&ch<=6){if(atm.withdraw(a[ch-1]))

System.out.println("取款成功!");else

System.out.println("余额不足!");

}else if(ch==7){

System.out.println("请输入取款金额:");

num=in.nextInt();if(atm.withdraw(num))

System.out.println("取款成功!");else 

System.out.println("余额不足!");

}else 

System.out.println("输入有误!");

System.out.println("当前余额:"+atm.getRest()+"");break;case 3:

System.out.println("账户号:");

String s=in.next();

System.out.println("转账金额:");int i=in.nextInt();if(atm.transfer(s, i))

System.out.println("转账成功!");else

System.out.println("转账失败!");

System.out.println("当前余额:"+atm.getRest()+"");break;case 4:

System.out.println("输入六位数密码:");

String p=in.next();

atm.setPassword(p);break;case 5:

System.out.println("当前余额:"+atm.getRest()+"");break;

 

}

}

}else

System.out.println("密码错误!");

}

}

class PersonalAccount{                 //首先用类封装个人属性private String passWord="123456";

@SuppressWarnings("unused")private String number;//银行卡号private int money=0;public int getMoney(){return money;}public void setPw(String s){passWord=s;}public void addMoney(int x){money+=x;}public void minusMoney(int x){money-=x;}public boolean whetherPwTrue(String s){if(s.equals(passWord))return true;else return false;

}

}

abstract class PATM{                //PATM抽象类用来定义需求的抽象方法public abstract boolean withdraw(int x);public abstract void save(int x);public abstract boolean transfer(String s,int x);public abstract boolean ifPass(String s);public abstract int getRest();public abstract void setPassword(String s);

}

 

class ATM extends PATM{          //ATM继承抽象类来并实现抽象方法private String numbers[]={"3235635","3256894","3265894","6589458"};private PersonalAccount account=new PersonalAccount();public boolean withdraw(int x) {if(x>account.getMoney())return false;else{

account.minusMoney(x);return true;

}

}public void save(int x) {

account.addMoney(x);

}public boolean transfer(String s, int x) {

boolean flag=false;for(int i=0;i<numbers.length;i++)if(s.equals(numbers[i])) flag=true;if(x>account.getMoney()) flag=false;if(x<=account.getMoney()&&flag) account.minusMoney(x);;return flag;

}public boolean ifPass(String s) {return account.whetherPwTrue(s);

}public int getRest() {return account.getMoney();

}public void setPassword(String s) {

account.setPw(s);

}

}

posted on 2016-11-18 23:17  *顺其自然*  阅读(239)  评论(0编辑  收藏  举报

导航