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 }
View Code
 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 }
View Code

备注:

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 }
View Code

三、接口

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

   备注回头看这个代码并没有完全的体现接口的思想(将类特有共能放在接口再在类中实现),可修改为:不实现模板类,分拆银行特有功能接口类,各银行子类直接继承银行基础类并实现对应的扩展功能接口,这样做更能体现接口特性,灵活性较高,但代码复用性较低,重复代码较多。

 

  

posted @ 2018-08-21 22:32  Kanekiyi  阅读(260)  评论(0编辑  收藏  举报