面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
(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);
}
}
实验结果截图:
分析:当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。
如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。
(2)用多态方法模拟ATM操作流程
源代码:
package bokeyuan;
import java.util.Scanner;
public class ATMTest {
public static void main(String[] args) {
ABCATM atm=new ABCATM();
UnionPay abc=new ABCImpl(3000,1603);
atm.insertCard(abc);
atm.allMenu();
}
}
//农行ATM
class ABCATM{
UnionPay card;
Scanner sc=new Scanner(System.in);
public void insertCard(UnionPay card){
this.card=card;
}
public void outCard(){
card=null;
}
public void showBalance(){ //显示余额
System.out.println("卡内余额:"+card.getBalance());
}
public void takeMoney(){ //取钱
System.out.println("请输入取钱金额:");
double number=sc.nextDouble();
if(card.drawMoney(number)){
System.out.println("取款成功!");
}else{
System.out.println("取款失败!");
}
}
public void payTelBill(){ //电话缴费
if(card instanceof ABCImpl){
ABCImpl abccard=(ABCImpl)card;
System.out.println("请输入电话号码:");
String phoneNum=sc.next();
while(phoneNum.length()!=11){
System.out.println("请输入电话号码:");
phoneNum=sc.next();
}
if(phoneNum.length()==11){
System.out.println("请输入缴费金额:");
double calls=sc.nextDouble();
if(abccard.payTel(phoneNum,calls)){
System.out.println("缴费成功!");
}else{
System.out.println("缴费失败!");
}
}else{
System.out.println("您输入的电话号码有误!");
}
}else{
System.out.println("您的银行卡非农行卡,不支持电话缴费");
}
}
public void allMenu(){ //功能菜单
do{
System.out.println("请输入密码:");
int input=sc.nextInt();
if(card.checkPwd(input)){
System.out.println("请选择功能:1.查询余额 2.电话缴费 3.取款 0.退出");
int a=sc.nextInt();
if(a==0){
System.out.println("退出系统!");
break;
}else{
switch(a){
case 1:showBalance();
break;
case 2:payTelBill();
break;
case 3:takeMoney();
break;
default:System.out.println("非法输入!");
}
}
break;
}else{
System.out.println("密码错误!");
System.out.println("请输入密码:");
input=sc.nextInt();
}
}while(true);
}
}
//银联接口
interface UnionPay {
public boolean drawMoney(double number); //取钱
public boolean checkPwd(int input); //验证密码
public double getBalance(); //显示余额
}
//农行卡接口
interface ABC extends UnionPay{
public boolean payTel(String phoneNum,double calls); //支付电话费
}
//实现农行卡接口
class ABCImpl implements ABC{
private double money;
private int pwd;
public ABCImpl(double money,int pwd){
this.money=money;
this.pwd=pwd;
}
public boolean payTel(String phoneNum,double calls){
if(phoneNum.length()==11&&calls<money){
money-=calls;
return true;
}
return false;
}
public boolean drawMoney(double number){
if(number<money){
money-=number;
return true;
}
return false;
}
public boolean checkPwd(int input){
if(pwd==input){
return true;
}
return false;
}
public double getBalance(){
return money;
}
}
运行结果: