Java面向对象(六):抽象方法 & 接口 & 递归
一、抽象类、抽象方法
1.1 定义:
子类继承父类时,重写了父类的方法,这个方法在父类中没有具体的实现内容,只是声明。具体的方法体由子类
继承时重写,那么这个方法被称为抽象方法,这个父类则为抽象类。用关键字abstract修饰
抽象方法只包含一个方法名,而没有方法体。抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
1.2 抽象类与抽象方法之间的关联
1、抽象类可以没有抽象方法,可以有成员方法成员变量;
2、包含抽象方法的类一定是抽象类。
1.3 子类继承抽象类则:
1、若子类为非抽象类,则一定要重写父类中的抽象方法;
2、若子类为抽象类,则可以不用实现父类的抽象方法。
例程:studyAbstract包:AbstractDemo1.java
1 package studyAbstract; 2 /** 3 * @author Kanekiyi 4 *抽象类与抽象方法 5 * 6 * **/ 7 public abstract class AbstractDemo1 { 8 String name; 9 int age; 10 11 /* 12 * 抽象方法没有方法体 13 * 有抽象方法的类一定是抽象类 14 * 15 * */ 16 public abstract void study(); 17 protected abstract void study2(); 18 abstract void study3(); 19 //private abstract void study3(); 20 //public static abstract void study4(); 21 22 //抽象类中可以有成员变量和成员方法以及构造方法 23 public void eat() { 24 System.out.println("我吃西红柿"); 25 } 26 27 public AbstractDemo1(String name, int age) { 28 super(); 29 this.name = name; 30 this.age = age; 31 System.out.println("父类有参构造"); 32 33 } 34 35 public AbstractDemo1() { 36 super(); 37 System.out.println("父类无参构造"); 38 39 // TODO Auto-generated constructor stub 40 } 41 42 }
1 package studyAbstract; 2 3 public class TextAbstractDemo1 extends AbstractDemo1 { 4 5 //抽象类不能被实例化 6 //AbstractDemo1 ad = new AbstractDemo1(); 7 8 //如果子类为非抽象类则必须实现抽象父类的抽象方法 9 public void study() { 10 System.out.println("我爱学习"); 11 } 12 13 @Override 14 protected void study2() { 15 // TODO Auto-generated method stub 16 17 } 18 19 @Override 20 void study3() { 21 // TODO Auto-generated method stub 22 23 } 24 25 public static void main(String[] args) { 26 TextAbstractDemo1 ad = new TextAbstractDemo1(); 27 ad.study2(); 28 29 } 30 31 }
备注:
1、abstract与哪些关键字不能共存?
final:不能共存
static:不能共存
private: 不能共存
2、abstract类能不能有构造函数?
能有。构造函数作用:供子类继承时初始化成员变量
二、递归
方法执行过程中调用方法自身。
例程:假设一对新生的小白兔从第三个月开始生一对小白兔,以后每个月都生一对小白兔
新生的小白兔也从第三个月开始生小小白兔,求第n个月共有多少对小白兔。
分析:小白兔随月份增加小白兔数量为:1 1 2 3 5 8 13 21
代码:DiGUiDemo.java
1 package studyAbstract; 2 /** 3 * 递归练习 4 * 例程:假设一对新生的小白兔从第三个月开始生一对小白兔,以后每个月都生一对小白兔 5 新生的小白兔也从第三个月开始生小小白兔,求第n个月共有多少对小白兔。 6 分析:小白兔随月份增加小白兔数量为:1 1 2 3 5 8 13 21 7 规律:从第三个数开始,每个数为之前两个数的和; 8 * 9 * 10 * **/ 11 public class DiGuiDemo { 12 13 int sum; 14 public int getNum(int mounth) { 15 16 if(mounth==1 || mounth==2) { 17 sum = 1; 18 } else { 19 //从第三个月开始每个月的兔子对数为上两个月的和 20 sum = getNum(mounth-1) +getNum(mounth-2); 21 22 } 23 return sum; 24 } 25 26 public static void main(String[] args) { 27 DiGuiDemo DGD = new DiGuiDemo(); 28 int mounth =8; 29 30 System.out.println(mounth+"个月后共有兔子"+DGD.getNum(mounth)+"对"); 31 } 32 33 }
三、接口
3.1 定义:
在Java中是一个抽象类型,是抽象方法的集合。用interface修饰
// 一个类通过继承接口的方式继承接口的抽象方法。接口可看作一个特殊的抽象类(存疑)
3.2 接口特点:
1、成员变量:
接口中的成员变量都为常量;默认修饰符:public static final
2、接口中不能有构造函数;
3、成员方法:
接口中的成员方法都为抽象方法;默认修饰符:public abstract
3.3 接口与抽象类区别:
1、声明关键字:抽象类abstract ,接口Interface
2、成员变量:抽象类可以为变量。接口只能为常量
3、构造函数:抽象类有,接口无;
4、成员方法 :抽象类可以有非抽象方法的方法可以不写抽象方法,接口只能为抽象方法。
5、抽象类实现类与类之间的共性。接口实现类的扩展性功能。
6、接口不是被类继承了,而是要被类实现。接口支持多继承。
3.4 接口的多继承与多实现:
1、接口与接口之间可以多继承,extends后面用逗号隔开;
2、类可以实现多个接口用关键字implements实现。
备注:
1、程序实现过程中可以将类的共性都放在抽象类中,每个类的特征性都放在接口中;
2、非抽象类实现了接口必须重写接口的方法;抽象类可以不实现接口的方法,其子类若为非抽象类需要实现接口的方法。
3、若父类实现了接口的抽象方法其子类可以不实现父类的抽象方法。
练习:
利用接口与抽象类模拟银行功能实现,要求每个银行有取钱的基础功能 ,除了取钱功能外每个银行都有自己的特色功能,比如冲话费,网上支付,透支额度等;
功能参考如下:
分析:
将具有共性的功能封装在抽象类中 父类 Person类额外的抽烟功能,不具有共性。此时可以将该功能封装在一个接口中,哪个银行特有,直接
去实现该接口即可 。
参考代码:
1、实现银行基础类:
1 package textInterfaceUnionpay2; 2 3 import java.util.Scanner; 4 /*** 5 * 银联的基础类:银联下个银行共有的基础方法基础变量 6 * @author 89869 7 * 8 */ 9 public abstract class UnionpayBasis { 10 11 private Scanner sc = new Scanner(System.in); 12 private String password; 13 private double balance; 14 private boolean loginFlag; 15 private static String bankName; 16 17 //构造函数初始化登陆flag 18 public UnionpayBasis() { 19 super(); 20 this.loginFlag = false; 21 } 22 23 //封装成员变量 24 public Scanner getSc() { 25 return sc; 26 } 27 public void setSc(Scanner sc) { 28 this.sc = sc; 29 } 30 31 public String getPassword() { 32 return password; 33 } 34 public void setPassword(String password) { 35 this.password = password; 36 } 37 38 public double getBalance() { 39 return balance; 40 } 41 public void setBalance(double balance) { 42 this.balance = balance; 43 } 44 45 public boolean isLoginFlag() { 46 return loginFlag; 47 } 48 public void setLoginFlag(boolean loginFlag) { 49 this.loginFlag = loginFlag; 50 } 51 52 public static String getBankName() { 53 return bankName; 54 } 55 @SuppressWarnings("static-access") 56 public void setBankName(String bankName) { 57 this.bankName = bankName; 58 } 59 60 //银联的基础方法 61 public abstract boolean loginSystem(); 62 public abstract void drawMoney(); 63 64 }
2、银行的扩展接口:
1 package textInterfaceUnionpay2; 2 /*** 3 * 接口:银联的扩展功能 4 * @author 89869 5 * 6 */ 7 public interface UnionpayExpand { 8 9 //扩展功能:手机冲话费 10 public abstract void payPhoneBills(); 11 //扩展功能:在线支付 12 public abstract void onLinePayMent(); 13 14 }
3、银行的模板类:继承基础类,实现扩展功能接口
1 package textInterfaceUnionpay2; 2 3 import java.util.Scanner; 4 /**** 5 * 6 * 银联下银行的抽象模板类:继承基础类,实现扩展接口。 7 * 实现父类及接口的所以抽象方法,方便子类调用。 8 * @author 89869 9 * 10 */ 11 public abstract class UnionpayMoudle extends UnionpayBasis implements UnionpayExpand{ 12 //获取控制台对象 13 Scanner sc = getSc(); 14 //透支额度 15 private double overdraftlLmit ; 16 17 //封装透支额度 18 public double getOverdraftlLmit() { 19 return overdraftlLmit; 20 } 21 public void setOverdraftlLmit(double overdraftlLmit) { 22 this.overdraftlLmit = overdraftlLmit; 23 } 24 25 @Override//登陆系统 26 public boolean loginSystem() { 27 int conunt=0; 28 29 while (true) { 30 //用户输入密码 31 System.out.println("请在下方输入银行卡密码:"); 32 String inPassword = sc.next(); 33 34 //判断输入密码 是否和系统密码一样 35 if (getPassword().equals(inPassword)) { 36 System.out.println("密码输入正确!"); 37 System.out.println("用户登陆成功"); 38 setLoginFlag(true); 39 break; 40 } else { 41 ++conunt; 42 setLoginFlag(false); 43 int num = 3-conunt; 44 System.out.println("密码输入错误,你还有"+num+"次机会重新输入密码"); 45 } 46 47 if (conunt>2) { 48 System.out.println("密码连续输入错误3次,您的卡已经被锁定请到柜台办理!"); 49 break; 50 } 51 } 52 return isLoginFlag(); 53 } 54 55 @Override//取款 56 public void drawMoney() { 57 58 loop: while (isLoginFlag()) { 59 System.out.println("请输入你的取款金额"); 60 double drawMoney = getSc().nextDouble(); 61 62 //限额,若取款金额大于余额加透支额度的和则取款失败重新输入取款金额 63 if (drawMoney>getBalance()+getOverdraftlLmit()) { 64 System.out.println("您的余额不足请重新输入取款金额"); 65 continue loop; 66 } 67 68 //计算余额 69 setBalance(getBalance() - drawMoney); 70 double balance = getBalance(); 71 System.out.println("取钱成功,卡余额为:"+balance); 72 73 //退出系统 74 setLoginFlag(false); 75 } 76 //System.out.println("您还没有输入密码登陆,请输入密码后在登陆!"); 77 78 } 79 80 @Override//在线支付 81 public void onLinePayMent() { 82 // TODO Auto-generated method stub 83 System.out.println("***********欢迎使用在线支付功能***********"); 84 85 loginSystem(); 86 87 while (isLoginFlag()) { 88 System.out.println("请输入你的支付金额"); 89 double drawMoney = getSc().nextDouble(); 90 91 //限额 92 if (drawMoney>getBalance()+getOverdraftlLmit()) { 93 System.out.println("您的余额不足请存入现金后再交易!"); 94 //退出系统 95 setLoginFlag(false); 96 break; 97 } 98 99 //计算余额 100 setBalance(getBalance() - drawMoney); 101 double balance = getBalance(); 102 System.out.println("支付成功,银行卡余额为:"+balance); 103 104 //退出系统 105 setLoginFlag(false); 106 } 107 108 } 109 110 @Override//支付电话费 111 public void payPhoneBills() { 112 // TODO Auto-generated method stub 113 System.out.println("********欢迎使用支付电话费功能********"); 114 115 loginSystem(); 116 117 while (isLoginFlag()) { 118 119 System.out.println("请输入你的支付金额"); 120 double drawMoney = getSc().nextDouble(); 121 122 //限额 123 if (drawMoney>getBalance() + getOverdraftlLmit()) { 124 System.out.println("您的余额不足请存入现金后再交易!"); 125 //退出系统 126 setLoginFlag(false); 127 break; 128 } 129 130 //计算余额 131 setBalance(getBalance() - drawMoney); 132 double balance = getBalance(); 133 System.out.println("支付成功,银行卡余额为:"+balance); 134 135 //退出系统 136 setLoginFlag(false); 137 } 138 139 } 140 141 }
4、实现各个银行子类
1 package textInterfaceUnionpay2; 2 3 public class ICBC extends UnionpayMoudle{ 4 public static void main(String[] args) { 5 ICBC icbc = new ICBC(); 6 7 //设置登陆密码 8 icbc.setPassword("123456"); 9 //设置银行卡余额 10 icbc.setBalance(8000); 11 //设置银行名称 12 icbc.setBankName("中国工商银行"); 13 //设置透支额度 14 icbc.setOverdraftlLmit(0); 15 System.out.println("欢迎使用"+getBankName()+"!"); 16 17 //密码登陆系统 18 icbc.loginSystem(); 19 //取钱 20 icbc.drawMoney(); 21 //在线支付 22 icbc.onLinePayMent(); 23 24 } 25 26 } 27 28 另一个类文件: 29 package textInterfaceUnionpay2; 30 31 import java.util.Scanner; 32 33 public class ABC extends UnionpayMoudle{ 34 35 Scanner sc = getSc(); 36 public static void main(String[] args) { 37 ABC abc = new ABC(); 38 abc.setPassword("123456"); 39 abc.setBalance(8000); 40 abc.setBankName("中国农业银行"); 41 abc.setOverdraftlLmit(2000); 42 System.out.println("**************欢迎使用"+getBankName()+"**************"); 43 44 abc.loginSystem(); 45 abc.drawMoney(); 46 //手机话费支付 47 abc.payPhoneBills(); 48 } 49 50 }
备注:回头看这个代码并没有完全的体现接口的思想(将类特有共能放在接口再在类中实现),可修改为:不实现模板类,分拆银行特有功能接口类,各银行子类直接继承银行基础类并实现对应的扩展功能接口,这样做更能体现接口特性,灵活性较高,但代码复用性较低,重复代码较多。