OOP 4-6次题目集总结

Posted zhxjs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OOP 4-6次题目集总结相关的知识,希望对你有一定的参考价值。

前言:

    通过前一个月的基础学习,对Java有了一定的了解,在这一个月中学习的知识难度明显增加,题目集的难度也随之增加。第四次的题目集主要考察对LinkedHashSet、ArrayList、Java的封装性、LocalDate类、String类、Integer类、Scanner类等的了解和简单使用。第五次的题目集主要考察对正则表达式的理解和使用,以及对类与类之间聚合关系的建立和应用。第六次题目集则考察对继承、多态的理解和使用,以及对类的初步设计。相对而言,第4、5次题目集的难度较接近,而第6次题目集的难度增加较显著。

设计,分析与心得:

  第四次的题目集主要考察对LinkedHashSet、ArrayList、Java的封装性、LocalDate类、String类、Integer类、Scanner类等的了解和简单使用。考察的内容较多,但主要难点在于7-1的菜单计价程序。

  由于没有合理规划好时间,未在规定时间内完成7-1题目。借总结的机会再仔细理解一下题目意思和要求。

  输入内容包括桌号、时间、序号、菜品名称、份额、分数、增删菜品;程序需要完成计算并输出总价格(包含规定时间内打折情况)。

  根据题目要求,设计了Dish(菜品)、Record(记录)、Menu(菜单)、Order(点单)、Table(餐桌)五个类。类与类之间的关系主要是关联。

 

    第五次题目集考察聚合关系的应用,以7-5、7-6为例。

    7-5的类图如下所示(题目已给出):

 

    题目要求:程序需要实现1、求下n天 2、求前n天 3、求两个日期相差的天数,三个要求。结合题目要求和类图可知,题目需要将Year的对象设置成Month的属性,将Month的对象设置为Day的属性,将Day的对象设置为DateUtil的属性,应用类与类的聚合关系来实现题目需求。

  7-6的题目要求和7-5相近,同样是实现1、求下n天 2、求前n天 3、求两个日期相差的天数,这三个要求,不同点在于两道题目所采用的聚合的方式不同。7-5采用是的一层一层的聚合方式,而7-6直接上Year、Month、Day三个类的对象直接设置为DateUtil的属性,我认为两者相较,7-6的聚合方式在代码的书写上更加简洁明了,表达更加清楚,而7-5的代码在书写过程中有些冗长,比如在DateUtil类中需要获取year的值时,需要day.getMonth().getYear().getValue(),而7-6只需要year.getValue()。但7-5式的聚合更能反应出Year、Month、Day三个类之间的关联。 7-6的类图如下所示(题目已给出):

  在各个类方法的具体书写中,因为有第三次题目集7-4的基础,所以没有遇到太大的问题,需要注意的两个点在于Int的范围。在第一次写完提交后,发现整型数最大值测试和整数类型的最小值测试,两个测试点错误,所以将计算方法改为逐天增加或减少至所给的天数为0来求得前N天和后N天的日期。在计算两个两个日期间隔N天时,采用的是先通过equalTowDates(date)判断日期是否相等,再通过compareDates(date)判断日期的前后,然后再逐天累加计算相隔的天数。和第三次题目集7-4不同的在于这次的日期包含了先后的情况,而不是单一的前面输入的日期在前,后面输入的日期在后。

7-5代码如下:

import java.util.Scanner;

class DateUtil 
    private Day day;
//无参构造方法
    public DateUtil() 
    
//带参构造方法
    public DateUtil(Day day) 
        this.day = day;
    
//getter
    public Day getDay() 
        return day;
    
//setter
    public void setDay(Day day) 
        this.day = day;
    
//检查日期是否合法
    public boolean checkInputValidity()
        if(day.validate())
            return true;
         else 
            return false;
        
    
//比较日期前后
    public boolean compareDates(DateUtil date)
        if(day.getMonth().getYear().getValue() < date.day.getMonth().getYear().getValue()) 
            return true;
        else if(day.getMonth().getYear().getValue() == date.day.getMonth().getYear().getValue()
                && day.getMonth().getValue() < date.day.getMonth().getValue() ) 
            return true;
        else if(day.getMonth().getYear().getValue() == date.day.getMonth().getYear().getValue()
                && day.getMonth().getValue() == date.day.getMonth().getValue()
                && day.getValue() <= date.day.getValue()) 
            return true;
        else 
            return false;
        
    
//比较日期是否相等
    public boolean equalTowDates(DateUtil date)
        if(day.getMonth().getYear().getValue() == date.day.getMonth().getYear().getValue()
                && day.getMonth().getValue() == date.day.getMonth().getValue()
                && day.getValue() == date.day.getValue())
            return true;
         else 
            return false;
        
    
//显示日期
    public String showDate()
        return day.getMonth().getYear().getValue()+"-"+day.getMonth().getValue()+"-"+day.getValue();
    
//计算n天后
    public DateUtil getNextNDays(int n) 
        for (int i = 0; i < n; i++) 
            if(day.getMonth().getYear().isLeapYear()) 
                day.setMon_maxnum(29);
             else 
                day.setMon_maxnum(28);
            
            day.dayIncrement();
            day.resetMin();
            day.getMonth().resetMin();
        
        DateUtil date1 = new DateUtil(day);
        return date1;
    
//计算n天前
    public DateUtil getPreviousNDays(int n) 
        for (int i = 0; i < n; i++) 
            if(day.getMonth().getYear().isLeapYear()) 
                day.setMon_maxnum(29);
             else 
                day.setMon_maxnum(28);
            
            day.dayReduction();
            day.resetMax();
            day.getMonth().resetMax();
        
        DateUtil date2 = new DateUtil(day);
        return date2;
    
//计算日期相差天数
    public int getDaysofDates(DateUtil date) 
        int n = 0;
        while(!equalTowDates(date))
            if(compareDates(date))
                if(day.getMonth().getYear().isLeapYear()) 
                    day.setMon_maxnum(29);
                 else 
                    day.setMon_maxnum(28);
                
                day.dayIncrement();
                day.resetMin();
                day.getMonth().resetMin();
                n++;
             else 
                if(day.getMonth().getYear().isLeapYear()) 
                    day.setMon_maxnum(29);
                 else 
                    day.setMon_maxnum(28);
                
                day.dayReduction();
                day.resetMax();
                day.getMonth().resetMax();
                n++;
            
        
        return n;
    


class Year 
    private int value;
//无参构造方法
    public Year() 
    
//带参构造方法
    public Year(int value) 
        this.value = value;
    
//getter
    public int getValue() 
        return value;
    
//setter
    public void setValue(int value) 
        this.value = value;
    
    //判断是否为闰年
    public boolean isLeapYear()
        if(value % 4 == 0 && value % 100 != 0 || value % 400 == 0) 
            return true;
         else 
            return false;
        
    
//校验数据是否合法
    public boolean validate()
        if(value > 2050 || value < 1900)
            return false;
         else 
            return true;
        
    
//年份加一
    public void yearIncrement()
        value ++;
    
//年份减一
    public void yearReduction()
        value --;
    

class Month 
    private int value;
    private Year year;
//无参构造方法
    public Month() 
    
//带参构造方法
    public Month(int value, Year year) 
        this.value = value;
        this.year = year;
    
//getter
    public int getValue() 
        return value;
    
//setter
    public void setValue(int value) 
        this.value = value;
    
//getter
    public Year getYear() 
        return year;
    
//setter
    public void setYear(Year year) 
        this.year = year;
    
//月份复位为1
    public void resetMin()
        if(value > 12 )
            value = 1;
            year.yearIncrement();
        
    
//月份设置为12
    public void resetMax()
        if(value < 1)
            value = 12;
            year.yearReduction();
        

    

    //校验数据合法性
    public boolean validate()
        if((value <= 12 && value >= 1) && year.validate())
            return true;
         else 
            return false;
        
    
//月份增加
    public void monthIncrement()
        value ++;
    
//月份减少
    public void monthReduction()
        value --;
    


class Day 
    private int value;
    private Month month;
    private int[] mon_maxnum = 31,31,28,31,30,31,30,31,31,30,31,30,31,0;
//带参构造方法
    public Day(int value, Month month) 
        this.value = value;
        this.month = month;
    
//无参构造方法
    public Day() 
    
//getter
    public int getValue() 
        return value;
    
//setter
    public void setValue(int value) 
        this.value = value;
    
//getter
    public Month getMonth() 
        return month;
    
//setter
    public void setMonth(Month month) 
        this.month = month;
    
//getter
    public int[] getMon_maxnum() 
        return mon_maxnum;
    
//改变2月份的天数
    public void setMon_maxnum(int n) 
        this.mon_maxnum[2] = n;
    
//天数复原为1
    public void resetMin()
        if(value > mon_maxnum[month.getValue()] )
            value = 1;
            month.monthIncrement();
        
    
//天数变为前个月最大天数
    public void resetMax()
        if(value < 1 )
            value = mon_maxnum[month.getValue()-1];
            month.monthReduction();
        
    

    //校验数据合法性
    public boolean validate()
        if(value <= mon_maxnum[month.getValue()] && value >= 1 && month.validate())
            return true;
         else 
            return false;
        
    
//天数增加
    public void dayIncrement()
        value ++;

    
//天数减少
    public void dayReduction()
        value --;
    



public class Main 
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;

        int choice = input.nextInt();

        if (choice == 1)  // test getNextNDays method
            int m = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            Year year1 = new Year(year);
            Month month1 = new Month(month,year1);
            Day day1 = new Day(day,month1);
            DateUtil date = new DateUtil(day1);

            if (!date.checkInputValidity()) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            m = input.nextInt();

            if (m < 0) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            System.out.println(date.getNextNDays(m).showDate());
         else if (choice == 2)  // test getPreviousNDays method
            int n = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            Year year1 = new Year(year);
            Month month1 = new Month(month,year1);
            Day day1 = new Day(day,month1);
            DateUtil date = new DateUtil(day1);

            if (!date.checkInputValidity()) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            n = input.nextInt();

            if (n < 0) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            System.out.println(date.getPreviousNDays(n).showDate());
         else if (choice == 3)     //test getDaysofDates method
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            Year year1 = new Year(year);
            Month month1 = new Month(month,year1);
            Day day1 = new Day(day,month1);
            DateUtil fromDate = new DateUtil(day1);

            Year year2 = new Year(anotherYear);
            Month month2 = new Month(anotherMonth,year2);
            Day day2 = new Day(anotherDay,month2);
            DateUtil toDate = new DateUtil(day2);

            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) 
                System.out.println(fromDate.getDaysofDates(toDate));
             else 
                System.out.println("Wrong Format");
                System.exit(0);
            
        
        else
            System.out.println("Wrong Format");
            System.exit(0);
        

    

 

7-6代码如下:

import java.util.Scanner;

class DateUtil 
    private Day day;
    private Month month;
    private Year year;
    private int[] mon_maxnum = 31,31,28,31,30,31,30,31,31,30,31,30,31,0;
//无参构造方法
    public DateUtil() 
    
//带参构造方法
    public DateUtil(Day day, Month month, Year year) 
        this.day = day;
        this.month = month;
        this.year = year;
    

    public Day getDay() 
        return day;
    

    public void setDay(Day day) 
        this.day = day;
    

    public Month getMonth() 
        return month;
    

    public void setMonth(Month month) 
        this.month = month;
    

    public Year getYear() 
        return year;
    

    public void setYear(Year year) 
        this.year = year;
    

    public void setMon_maxnum(int n) 
        this.mon_maxnum[2] = n;
    
//检查日期是否合法
    public boolean checkInputValidity()
        //先判断输入的年份是否是闰年,改变2月份的天使
        if(year.isLeapYear()) 
            setMon_maxnum(29);
         else 
            setMon_maxnum(28);
        
        //检查日期
        if(month.validate() && year.validate() && day.getValue() <= mon_maxnum[month.getValue()] && day.getValue() >= 1)
            return true;
         else 
            return false;
        
    
//比较日期前后
    public boolean compareDates(DateUtil date)
        if(year.getValue() < date.getYear().getValue()) 
            return true;
        else if(year.getValue() == date.getYear().getValue()
                && month.getValue() < date.getMonth().getValue() ) 
            return true;
        else if(year.getValue() == date.getYear().getValue()
                && month.getValue() == date.getMonth().getValue()
                && day.getValue() <= date.day.getValue()) 
            return true;
        else 
            return false;
        
    
//判断日期是否相等
    public boolean equalTowDates(DateUtil date)
        if(year.getValue() == date.getYear().getValue()
                && month.getValue() == date.getMonth().getValue()
                && day.getValue() == date.day.getValue())
            return true;
         else 
            return false;
        
    
//显示日期
    public String showDate()
        return year.getValue()+"-"+month.getValue()+"-"+day.getValue();
    
//后n天
    public DateUtil getNextNDays(int n) 
        for (int i = 0; i < n; i++) 
            if(year.isLeapYear()) 
                setMon_maxnum(29);
             else 
                setMon_maxnum(28);
            
            day.dayIncrement();
            if(day.getValue() > mon_maxnum[month.getValue()])
                day.setValue(1);
                month.monthIncrement();
                if(month.getValue() > 12)
                    month.resetMin();
                    year.yearIncrement();
                
            
        
        DateUtil date1 = new DateUtil(day,month,year);
        return date1;
    
//前n天
    public DateUtil getPreviousNDays(int n) 
        for (int i = 0; i < n; i++) 
            if(year.isLeapYear()) 
                setMon_maxnum(29);
             else 
                setMon_maxnum(28);
            
            day.dayReduction();
            if(day.getValue() < 1)
                day.setValue(mon_maxnum[month.getValue() - 1]);
                month.monthReduction();
                if(month.getValue() < 1 )
                    month.resetMax();
                    year.yearReduction();
                
            
        
        DateUtil date2 = new DateUtil(day,month,year);
        return date2;
    
//求两个日前间相差的天数
    public int getDaysofDates(DateUtil date) 
        int n = 0;
        while(!equalTowDates(date))
            //先判断日期的前后
            if(compareDates(date))
                if(year.isLeapYear()) 
                    setMon_maxnum(29);
                 else 
                    setMon_maxnum(28);
                
                day.dayIncrement();
                if(day.getValue() > mon_maxnum[month.getValue()])
                    day.setValue(1);
                    month.monthIncrement();
                    if(month.getValue() > 12)
                        month.resetMin();
                        year.yearIncrement();
                    
                
                n++;
             else 
                if(year.isLeapYear()) 
                    setMon_maxnum(29);
                 else 
                    setMon_maxnum(28);
                
                day.dayReduction();
                if(day.getValue() < 1)
                    day.setValue(mon_maxnum[month.getValue() - 1]);
                    month.monthReduction();
                    if(month.getValue() < 1 )
                        month.resetMax();
                        year.yearReduction();
                    
                
                n++;
            
        
        return n;
    


class Year 
    private int value;
//无参构造方法
    public Year() 
    
//带参构造方法
    public Year(int value) 
        this.value = value;
    

    public int getValue() 
        return value;
    

    public void setValue(int value) 
        this.value = value;
    
    //判断是否为闰年
    public boolean isLeapYear()
        if(value % 4 == 0 && value % 100 != 0 || value % 400 == 0) 
            return true;
         else 
            return false;
        
    
    //校验数据是否合法
    public boolean validate()
        if(value > 2020 || value < 1820)
            return false;
         else 
            return true;
        
    
    //年份加一
    public void yearIncrement()
        value ++;
    
    //年份减一
    public void yearReduction()
        value --;
    

class Month 
    private int value;

//无参构造方法
    public Month() 
    
//带参构造方法
    public Month(int value) 
        this.value = value;
    

    public int getValue() 
        return value;
    

    public void setValue(int value) 
        this.value = value;
    

    //月份复位为1
    public void resetMin()
        if(value > 12 )
            value = 1;
        
    
    //月份设置为12
    public void resetMax()
        if(value < 1)
            value = 12;
        
    

    //校验数据合法性
    public boolean validate()
        if(value <= 12 && value >= 1)
            return true;
         else 
            return false;
        
    
//月份加一
    public void monthIncrement()
        value ++;
    
//月份减一
    public void monthReduction()
        value --;
    


class Day 
    private int value;

//带参构造方法
    public Day(int value) 
        this.value = value;
    
//无参构造方法
    public Day() 
    

    public int getValue() 
        return value;
    

    public void setValue(int value) 
        this.value = value;
    

//天数加一
    public void dayIncrement()
        value ++;
    
//天数减一
    public void dayReduction()
        value --;
    



public class Main 
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;

        int choice = input.nextInt();

        if (choice == 1)  // test getNextNDays method
            int m = 0;
            //输入日期
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());
            //构造对面
            Year year1 = new Year(year);
            Month month1 = new Month(month);
            Day day1 = new Day(day);
            DateUtil date = new DateUtil(day1,month1,year1);
            //检查日期是否合法
            if (!date.checkInputValidity()) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            m = input.nextInt();

            if (m < 0) 
                System.out.println("Wrong Format");
                System.exit(0);
            
            //输出结果
            System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " next " + m + " days is:");
            System.out.println(date.getNextNDays(m).showDate());
         else if (choice == 2)  // test getPreviousNDays method
            int n = 0;
            //输入日期
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());
            //构造对象
            Year year1 = new Year(year);
            Month month1 = new Month(month);
            Day day1 = new Day(day);
            DateUtil date = new DateUtil(day1,month1,year1);
            //检查日期是否合法
            if (!date.checkInputValidity()) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            n = input.nextInt();

            if (n < 0) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " previous " + n + " days is:");
            System.out.println(date.getPreviousNDays(n).showDate());
         else if (choice == 3)     //test getDaysofDates method
            //输入起始日期
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());
            //输入终止日期
            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            Year year1 = new Year(year);
            Month month1 = new Month(month);
            Day day1 = new Day(day);
            DateUtil fromDate = new DateUtil(day1,month1,year1);

            Year year2 = new Year(anotherYear);
            Month month2 = new Month(anotherMonth);
            Day day2 = new Day(anotherDay);
            DateUtil toDate = new DateUtil(day2,month2,year2);
            //判断数据是否合法即计算相差天数
            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) 
                System.out.println("The days between " + fromDate.showDate() +
                        " and " + toDate.showDate() + " are:"
                        + fromDate.getDaysofDates(toDate));
             else 
                System.out.println("Wrong Format");
                System.exit(0);
            
        
        else
            System.out.println("Wrong Format");
            System.exit(0);
        

    

 

  第六次题目集考察了对类的初步设计,以7-4和7-5为例:

7-4题目要求如文件所示:

93fc7ad6-5e85-445a-a759-5790d0baab28.pdf (ptausercontent.com)

  根据题目意思,需要设计中国银联(China UnionPay)、银行(Bank)、银行用户(User)、银行账户(Account)、银行卡(Card)、ATM(Automated Teller Machine)六个实体类。

类图设计如下:

  初步观察,银联中有多个银行,每个银行可以有多个用户,每个用户可以有多个账户,每个账户可以有多张银行卡,且要求银联,银行,用户,账户,银行卡均设计为独有的类,因此采用和第五次题目集7-5的相同形式,将类与类之间设置为聚合关系,从中国银联(China UnionPay)到银行卡(Card)。但由于类的数量较多,这种方式使得调用比较繁琐,特别是在对对象进行初始化时代码冗长难理解。

在7-5中增加了一些要求,具体如文件所示:

https://images.ptausercontent.com/60abe58e-09db-49b0-b9dc-219a33d2c073.pdf

  类的设计要求基本相同,但在设计过程中转变了一下思路,由于在7-5中的发现初始化过程的冗长,且再次仔细阅读题目后,发现目标的最终落脚处在于银行卡Card,后续的操作均以银行卡卡号匹配正确为准为基础。每张银行卡都有卡号、密码、用户、所属账户、所属银行,因此将聚合的形式从中国银联(China UnionPay)到银行卡(Card)改为从银行卡(Card)到中国银联(China UnionPay)。具体类图如下所示:

 

  题目的难度就主要在对类的设计和对题意的理解上,在跨行取款的计算中几次出现错误。多次试错后理解题意。按照题目要求,透支的那部分金额不管在跨行还是不跨行取款时都需要额外计算透支的手续费,而包括透支金额在内的所有取款金额都要计算跨行取款的手续费,意思为当使用信用卡透支取款时,透支部分的金额是需要计算两次手续费的。另一个多次错误的点在于判断金额是否满足所需取款的金额。正确的判断条件应该为手续费(如果是跨行取款、或者是透支取款)加上所需取款金额小于等于借记卡的余额或者信用卡的余额加信用卡的透支额度。还有一个难点在于对金额不足判断和取款后余额的计算。因为在7-5中,多了信用卡、透支情况、跨行取款情况,所以要进行分类讨论。分别计算在使用借记卡(无法透支)的非跨行取款和跨行取款,使用信用卡透支情况下跨行取款和非跨行取款,透支情况下跨行取款和非跨行取款六种情况。需要理顺情况和关系后才能正确完成题目。

 7-4代码如下:

import java.util.*;

class ChinaUnionPay 
    private Bank[] bank;

    public ChinaUnionPay() 
    

    public ChinaUnionPay(Bank[] bank) 
        this.bank = bank;
    


class Bank 
    private User[] users;
    private String bankName;

    public Bank() 
    

    public Bank(User[] users, String bankName) 
        this.users = users;
        this.bankName = bankName;
    

    public String getBankName() 
        return bankName;
    

    public void setBankName(String bankName) 
        this.bankName = bankName;
    

    public User[] getUsers() 
        return users;
    

    public void setUsers(User[] users) 
        this.users = users;
    


class User 
    private Account[] accounts;
    private String username;

    public User() 
    

    public User(Account[] accounts, String username) 
        this.accounts = accounts;
        this.username = username;
    

    public Account[] getAccounts() 
        return accounts;
    

    public void setAccounts(Account[] accounts) 
        this.accounts = accounts;
    

    public String getUsername() 
        return username;
    

    public void setUsername(String username) 
        this.username = username;
    


class Account 
    private Card[] cards;
    private String accountNum;
    private double balance;


    public Account(String accountNum, double balance) 
        this.accountNum = accountNum;
        this.balance = balance;
    

    public Account(Card[] cards, String accountNum, double balance) 
        this.cards = cards;
        this.accountNum = accountNum;
        this.balance = balance;
    

    public Card[] getCards() 
        return cards;
    

    public void setCards(Card[] cards) 
        this.cards = cards;
    

    public double getBalance() 
        return balance;
    

    public void setBalance(double balance) 
        this.balance = balance;
    

    public double showBalance()
        return balance;
    


class Card 
    private String cardNumber;
    private String password;

    public Card() 
    

    public Card(String cardNumber, String password) 
        this.cardNumber = cardNumber;
        this.password = password;
    

    public String getCardNumber() 
        return cardNumber;
    

    public void setCardNumber(String cardNumber) 
        this.cardNumber = cardNumber;
    

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    



class ATM 
    private String number;
    String belongToBank;

    public ATM() 
    

    public ATM(String number, String belongToBank) 
        this.number = number;
        this.belongToBank = belongToBank;
    

    public String getNumber() 
        return number;
    

    public void setNumber(String number) 
        this.number = number;
    

    public String getBelongToBank() 
        return belongToBank;
    

    public void setBelongToBank(String belongToBank) 
        this.belongToBank = belongToBank;
    


class Action 
    private Bank[] banks;
    private ATM[] atms;

    public Action() 
    

    public Action(Bank[] banks, ATM[] atms) 
        this.banks = banks;
        this.atms = atms;
    

    public boolean checkCardExist(String cardNumber)
        int i = 0;
        int j = 0;
        int k = 0;
        int m = 0;
        int n = 0;
        for(i = 0; i < banks.length; i++)
            for(j = 0; j < banks[i].getUsers().length; j++)
                for(k = 0; k < banks[i].getUsers()[j].getAccounts().length; k++)
                    for(m = 0; m < banks[i].getUsers()[j].getAccounts()[k].getCards().length; m++)
                        if(cardNumber.equals(banks[i].getUsers()[j].getAccounts()[k].getCards()[m].getCardNumber()))
                            return true;
                        
                    
                
            
        
        return false;
    

    public boolean checkAtmExist(String atmNumber)
        int s = 0;
        while(s < atms.length)
            if(atmNumber.equals(atms[s].getNumber()))
                return true;
            
            s++;
        
        return false;
    

    public boolean checkCardPassword(String cardPassword)
        String str = "88888888";
        if(cardPassword.equals(str))
            return true;
         else 
            return false;
        
    

    public boolean checkBalance(String cardNumber, String money) 
        double money_s = Double.parseDouble(money);
        int i = 0;
        int j = 0;
        int k = 0;
        int m = 0;
        int n = 0;
        for(i = 0; i < banks.length; i++)
            for(j = 0; j < banks[i].getUsers().length; j++)
                for(k = 0; k < banks[i].getUsers()[j].getAccounts().length; k++)
                    for(m = 0; m < banks[i].getUsers()[j].getAccounts()[k].getCards().length; m++)
                        if(cardNumber.equals(banks[i].getUsers()[j].getAccounts()[k].getCards()[m].getCardNumber()))
                            if(money_s > banks[i].getUsers()[j].getAccounts()[k].showBalance())
                                return false;
                            
                        
                    
                
            
        
        return true;
    

    public boolean checkInterBankAction(String cardNumber, String atmNumber)
        int atmNum = Integer.parseInt(atmNumber) - 1;
        int i = 0;
        int j = 0;
        int k = 0;
        int m = 0;
        int n = 0;
        for(i = 0; i < banks.length; i++)
            for(j = 0; j < banks[i].getUsers().length; j++)
                for(k = 0; k < banks[i].getUsers()[j].getAccounts().length; k++)
                    for(m = 0; m < banks[i].getUsers()[j].getAccounts()[k].getCards().length; m++)
                        if(cardNumber.equals(banks[i].getUsers()[j].getAccounts()[k].getCards()[m].getCardNumber()))
                            if(!atms[atmNum].getBelongToBank().equals(banks[i].getBankName()))
                                return false;
                            
                        
                    
                
            
        
        return true;
    

    public void showBalance(String cardNumber)
        int i = 0;
        int j = 0;
        int k = 0;
        int m = 0;
        int n = 0;
        loop:for(i = 0; i < banks.length; i++)
            for(j = 0; j < banks[i].getUsers().length; j++)
                for(k = 0; k < banks[i].getUsers()[j].getAccounts().length; k++)
                    for(m = 0; m < banks[i].getUsers()[j].getAccounts()[k].getCards().length; m++)
                        if(cardNumber.equals(banks[i].getUsers()[j].getAccounts()[k].getCards()[m].getCardNumber()))
                            System.out.println("¥"+String.format("%.2f",banks[i].getUsers()[j].getAccounts()[k].showBalance()));
                            break loop;
                        
                    
                
            
        
    

    public void deposit(String cardNumber,double money,String atmNumber)
        int i = 0;
        int j = 0;
        int k = 0;
        int m = 0;
        int n = 0;
        loop:for(i = 0; i < banks.length; i++)
            for(j = 0; j < banks[i].getUsers().length; j++)
                for(k = 0; k < banks[i].getUsers()[j].getAccounts().length; k++)
                    for(m = 0; m < banks[i].getUsers()[j].getAccounts()[k].getCards().length; m++)
                        if(cardNumber.equals(banks[i].getUsers()[j].getAccounts()[k].getCards()[m].getCardNumber()))
                            banks[i].getUsers()[j].getAccounts()[k].setBalance(banks[i].getUsers()[j].getAccounts()[k].showBalance() - money);
                            System.out.println(banks[i].getUsers()[j].getUsername()+"在"+banks[i].getBankName()+"的"+atmNumber+"号ATM机上存款¥"+String.format("%.2f",-money));
                            System.out.println("当前余额为¥"+String.format("%.2f",banks[i].getUsers()[j].getAccounts()[k].showBalance()));
                            break loop;
                        
                    
                
            
        
    

    public void withdraw(String cardNumber,double money,String atmNumber)
        int i = 0;
        int j = 0;
        int k = 0;
        int m = 0;
        int n = 0;
        loop:for(i = 0; i < banks.length; i++)
            for(j = 0; j < banks[i].getUsers().length; j++)
                for(k = 0; k < banks[i].getUsers()[j].getAccounts().length; k++)
                    for(m = 0; m < banks[i].getUsers()[j].getAccounts()[k].getCards().length; m++)
                        if(cardNumber.equals(banks[i].getUsers()[j].getAccounts()[k].getCards()[m].getCardNumber()))
                            banks[i].getUsers()[j].getAccounts()[k].setBalance(banks[i].getUsers()[j].getAccounts()[k].showBalance() - money);
                            System.out.println(banks[i].getUsers()[j].getUsername()+"在"+banks[i].getBankName()+"的"+atmNumber+"号ATM机上取款¥"+String.format("%.2f",money));
                            System.out.println("当前余额为¥"+String.format("%.2f",banks[i].getUsers()[j].getAccounts()[k].showBalance()));
                            break loop;
                        
                    
                
            
        
    


public class Main 
    public static void main(String[] args) 
        Scanner in = new Scanner(System.in);
        Card card01 = new Card("6217000010041315709","88888888");
        Card card02 = new Card("6217000010041315715","88888888");
        Card[] cards1 = new Card[2];
        cards1[0] = card01;
        cards1[1] = card02;
        Account account01 = new Account(cards1,"3217000010041315709 ",10000.00);

        Card card03 = new Card("6217000010041315718","88888888");
        Card[] cards2 = new Card[1];
        cards2[0] = card03;
        Account account02 = new Account(cards2,"3217000010041315715",10000.00);

        Account[] accounts1 = new Account[2];
        accounts1[0] = account01;
        accounts1[1] = account02;
        User user1 = new User(accounts1,"杨过");

        Card card04 = new Card("6217000010051320007","88888888");
        Card[] cards3 = new Card[1];
        cards3[0] = card04;
        Account account03 = new Account(cards3,"3217000010051320007",10000.00);

        Account[] accounts2 = new Account[1];
        accounts2[0] = account03;
        User user2 = new User(accounts2,"郭靖");

        Card card05 = new Card("6222081502001312389","88888888");
        Card[] cards4 = new Card[1];
        cards4[0] = card05;
        Account account04 = new Account(cards4,"3222081502001312389",10000.00);

        Card card06 = new Card("6222081502001312390","88888888");
        Card[] cards5 = new Card[1];
        cards5[0] = card06;
        Account account05 = new Account(cards5,"3222081502001312390",10000.00);

        Card card07 = new Card("6222081502001312399","88888888");
        Card card08 = new Card("6222081502001312400","88888888");
        Card[] cards6 = new Card[2];
        cards6[0] = card07;
        cards6[1] = card08;
        Account account06 = new Account(cards6,"3222081502001312399",10000.00);

        Account[] accounts3 = new Account[3];
        accounts3[0] = account04;
        accounts3[1] = account05;
        accounts3[2] = account06;
        User user3 = new User(accounts3,"张无忌");

        Card card09 = new Card("6222081502051320785","88888888");
        Card[] cards7 = new Card[1];
        cards7[0] = card09;
        Account account07 = new Account(cards7,"3222081502051320785",10000.00);

        Card card010 = new Card("6222081502051320786","88888888");
        Card[] cards8 = new Card[1];
        cards8[0] = card010;
        Account account08 = new Account(cards8,"3222081502051320786",10000.00);

        Account[] accounts4 = new Account[2];
        accounts4[0] = account07;
        accounts4[1] = account08;
        User user4 = new User(accounts4,"韦小宝");

        User[] users1 = new User[2];
        users1[0] = user1;
        users1[1] = user2;
        User[] users2 = new User[2];
        users2[0] = user3;
        users2[1] = user4;

        Bank bank1 = new Bank(users1,"中国建设银行");
        Bank bank2 = new Bank(users2,"中国工商银行");

        Bank[] banks = new Bank[2];
        banks[0] = bank1;
        banks[1] = bank2;

        ATM atm01 = new ATM("01","中国建设银行");
        ATM atm02 = new ATM("02","中国建设银行");
        ATM atm03 = new ATM("03","中国建设银行");
        ATM atm04 = new ATM("04","中国建设银行");
        ATM atm05 = new ATM("05","中国工商银行");
        ATM atm06 = new ATM("06","中国工商银行");

        ATM[] atms = new ATM[6];
        atms[0] = atm01;
        atms[1] = atm02;
        atms[2] = atm03;
        atms[3] = atm04;
        atms[4] = atm05;
        atms[5] = atm06;

        Action action = new Action(banks,atms);
        String str = "null";
        while(!str.equals("#"))
            str = in.nextLine();
            String[] inputStr= str.split("\\\\s+");
            if(inputStr.length > 1) 
                if (!action.checkCardExist(inputStr[0])) 
                    System.out.println("Sorry,this card does not exist.");
                    break;
                
                if (!action.checkAtmExist(inputStr[2]))
                    System.out.println("Sorry,the ATM\'s id is wrong.");
                    break;
                
                if (!action.checkCardPassword(inputStr[1]))
                    System.out.println("Sorry,your password is wrong.");
                    break;
                
                if (!action.checkBalance(inputStr[0],inputStr[3]))
             

什么是OOP

OOP即面向对象程序设计,全称为Object Oriented Programming,是一种计算机编程架构。其本质是以建立模型体现出来的抽象思维过程和面向对象的方法,模型是用来反映现实世界中事物特征的。

面向对象程序设计以对象为核心,该方法认为程序由一系列对象组成。类是对现实世界的抽象,包括表示静态属性的数据和对数据的操作,对象是类的实例化。对象间通过消息传递相互通信,来模拟现实世界中不同实体间的联系。在面向对象的程序设计中,对象是组成程序的基本模块。

扩展资料:

面向对象程序设计的优点:

1、数据抽象的概念可以在保持外部接口不变的情况下改变内部实现,从而减少甚至避免对外界的干扰;

2、通过继承大幅减少冗余的代码,并可以方便地扩展现有代码,提高编码效率,也减低了出错概率,降低软件维护的难度;

3、结合面向对象分析、面向对象设计,允许将问题域中的对象直接映射到程序中,减少软件开发过程中中间环节的转换过程;

4、通过对对象的辨别、划分可以将软件系统分割为若干相对为独立的部分,在一定程度上更便于控制软件复杂度;

5、以对象为中心的设计可以帮助开发人员从静态(属性)和动态(方法)两个方面把握问题,从而更好地实现系统。

参考资料来源:百度百科-OOP

参考技术A   是面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。
  简介:
  OOP: Object Oriented Programming,面向对象的程序设计。所谓“对象”在显式支持面向对象的语言中,一般是指类在内存中装载的实例,具有相关的成员变量和成员函数(也称为:方法)。面向对象的程序设计完全不同于传统的面向过程程序设计,它大大地降低了软件开发的难度,使编程就像搭积木一样简单,是当今电脑编程的一股势不可挡的潮流。
  OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。OOP 主要有以下的概念和组件:
  组件 - 数据和功能一起在运行着的计算机程序中形成的单元,组件在 OOP 计算机程序中是模块和结构化的基础。
  抽象性 - 程序有能力忽略正在处理中信息的某些方面,即对信息主要方面关注的能力。
  封装 - 也叫做信息封装:确保组件不会以不可预期的方式改变其它组件的内部状态;只有在那些提供了内部状态改变方法的组件中,才可以访问其内部状态。每类组件都提供了一个与其它组件联系的接口,并规定了其它组件进行调用的方法。
  多态性 - 组件的引用和类集会涉及到其它许多不同类型的组件,而且引用组件所产生的结果得依据实际调用的类型。
  继承性 - 允许在现存的组件基础上创建子类组件,这统一并增强了多态性和封装性。典型地来说就是用类来对组件进行分组,而且还可以定义新类为现存的类的扩展,这样就可以将类组织成树形或网状结构,这体现了动作的通用性。
  由于抽象性、封装性、重用性以及便于使用等方面的原因,以组件为基础的编程在脚本语言中已经变得特别流行。Python 和 Ruby 是最近才出现的语言,在开发时完全采用了 OOP 的思想,而流行的 Perl 脚本语言从版本5开始也慢慢地加入了新的面向对象的功能组件。用组件代替“现实”上的实体成为 JavaScript(ECMAScript) 得以流行的原因,有论证表明对组件进行适当的组合就可以在英特网上代替 HTML 和 XML 的文档对象模型(DOM)。
参考技术B 在本文(也是本系列的第五部分)中,Teodor 解释了什么是面向对象编程,何时使用它以及它是如何在 Perl 中工作的。面向对象编程(OOP)是一种强大的编程技术,但它不是万能药。优秀的程序员必须理解如何使用它,并且必须知道何时依赖更传统的编程技术。在 Perl 中使用 OOP 很简单。与 C++ 和 Java 等限制性更强的 OOP 语言不同,Perl 中的 OOP 很少对程序员施加强制性约束。OOP 是对每一名程序员的工具箱的必要补充,并且是用于扩展可用 Perl 解决的问题范围的非常有用的技术。什么是面向对象编程(OOP)?OOP 是一种用于解决问题的编程方法或通用方法。与之相反,算法是用于解决特定问题的 特定方法。OOP 天生是一种强有力的方法;它往往使过程型和函数型编程方法与该问题较少相关,并且除非它与过程型和函数型编程方法的混合对其极其有益,否则它们之间不会很好地结合在一起。在 Perl 中,这种强大的力量有所减弱,但仍然很好地存在着。 本文讨论 Perl 中的 OOP 对比函数型和过程型编程的基本知识,并演示如何在 Perl 程序和模块中使用 OOP。请记住,本文只是一篇概述,而不是对 Perl 中 OOP 所有方面的详尽解释。这样的详尽解释需要几本书才能讲完,并且已经被写过几次了。有关详细信息,请参阅本文稍后的 参考资料。 究竟什么是 OOP?OOP 是一种通过使用对象来解决问题的技术。在编程术语中,对象是这样一些实体:它们的特性和行为是解决手头问题所必需的。这个定义本应该更详细些,但是做不到,因为当今计算机行业中 OOP 方法的种类之多简直难以想象。在Perl 编程环境中,OOP 并不是使用该语言所必需的。Perl 版本 5 和更高版本鼓励使用 OOP,但确切地说不要求这样做。所有 Perl 库都是模块,这意味着它们至少使用 OOP 的基本部分。而且,大多数 Perl 库都作为对象实现,这意味着用户必须通过良好定义的接口将它们作为具有特定行为和特性的 OOP 实体来使用。回页首基本的 OO 编程语言特性通常,有三个语言特性是 OOP 编程语言所必需的。它们是继承、多态性和封装。Perl 支持继承。当一个对象(子对象)使用另一个对象作为起点(父对象),并且随后在需要时修改其特性和行为时,就要用到 继承。子-父关系是 OOP 所必需的,因为它使得在其它对象基础上构建对象成为可能。这种重用是使 OOP 成为程序员宠儿的好处之一。 有两种继承:单一继承和多重继承。 单一继承要求子对象只有一个父对象,而 多重继承更自由(与实际生活一样,在编程过程中具有两个以上的父对象会导致混乱并使子对象难以工作,因此,不要过多使用多重继承)。尽管两个或两个以上的父对象实际上很少见,但 Perl 支持多重继承。 多态性(来自希腊语,表示“很多形态”)是使一个对象被看成另一个对象的技术。这有点复杂,那么我举个例子。比方说,您有一个绵羊牧场,里面有四只绵羊(绵羊属),但是您刚刚买了两只山羊(山羊属)和一只德国牧羊犬(犬科犬属)。您一共有多少动物?您得把所有的绵羊、山羊和狗加起来,结果是 7 只。其实您刚刚应用了多态性,即为了计算,把三种不同种类的动物当成一种通用类型(“动物”)对待。如果您把绵羊、山羊和狗当成哺乳动物看待,这就是一个简单的信心飞跃。生物学家每天都以这种方式使用多态性,而程序员则以从其它科学领域“窃用”(我是指“重用”)好主意闻名。Perl 完全支持 多态性。但它用得不是很频繁,因为 Perl 程序员看起来更喜欢用对象特性、而不是通过修改继承的行为来修改通用行为。这意味着您更可能看到创建三个 IO::Socket::INET 对象的代码:一个对象用于在端口 234 接收和发送 UDP 包、一个对象用于在端口 80 接收 TCP 包,还有一个对象在端口 1024 发送 TCP 包,而不大会看到对第一种情况使用 IO::Socket::INET::UDPTransceiver 、对第二种情况使用 IO::Socket::INET::TCPReceiver 而对第三种情况使用 IO::Socket::TCPTransmitter 的代码。这就象是在生物学术语中说狗和山羊都是哺乳动物,但是山羊属于山羊属,而狗属于犬属。 OOP 纯化论者认为每件事都应该正确分类,但是 Perl 程序员根本不是纯化论者。他们往往更不拘束于 OOP 规则,这使得他们在聚会中比 OOP 纯化论者更快乐。封装指的是以这样一种方式包含对象行为和特性:除非对象作者允许,否则用户无法访问该对象的行为和特性。在这种方式下,对象用户无法做不准他们做的事,无法访问不准他们访问的数据,并且通常是有害数据。Perl 通常用松弛的方法封装。请参阅 清单1。 回页首为什么说 OOP 是一种强有力的方法?返回到我们最初的 OOP 如何是一种强有力的方法这一主题,我们现在可以看到 OOP 结合了几个关键的概念,这使得它很难与过程型和函数型编程(PP 和 FP)混合使用。首先,PP 和 FP 都没有继承或类多态性的概念,因为在 PP 和 FP 中根本就没有类。在 PP 和 FP 中存在封装,但只在过程型级别,从来不作为类或对象属性封装。既然程序员不怕麻烦来使用这些基本的 OOP 工具,那就意味着程序员通常更可能对整个项目使用 OOP,而不是混合不兼容的方法。有人可能争论说所有程序最终都归结为指令的过程型执行,因此无论 OOP 程序实现得有多纯,每个 OOP 程序都在其函数(也称为方法)和创建第一个对象(该对象做其余工作)的代码中包含过程型代码。甚至象 Java 那样接近“纯”OOP 的语言都无法避免地需要一个 main() 函数。因此,看起来 OOP 只是 PP 的一个子集。但是这种 OOP 向序列指令的归结和实际为每个操作所执行的汇编程序指令一样,都不是系统架构设计师或程序员所关心的事。请记住,OOP 本身只是一种方法,而不是目的。 OOP 与过程型编程方法合作得不是很好,因为它集中在对象上,而过程型编程基于过程(我们将 过程大致定义为不使用 OOP 技术就可以得到的函数,而将 方法定义为只有在对象中才能得到的函数)。正如方法一样,过程只是由用户调用的函数,但是二者之间有一些差异。 过程不使用对象数据。必须在它们的参数列表中为它们传递数据,或者它们必须使用所在作用域中的数据。过程可以访问调用它时传递给它的任何数据,甚至整个程序的全局数据。方法应该只访问它们对象的数据。实际上,方法的函数作用域通常是包含该方法的对象。常常发现过程使用全局数据,尽管只有在绝对必要时才应该这样做。应该尽快重写使用全局数据的方法。过程通常用几个参数调用其它过程。方法应该只有几个参数,并且它们调用其它方法的次数比其它过程更多。函数型编程(FP)与 OOP 配合不好有几个原因。最重要的原因是 FP 基于用来解决问题的详细函数型方法,而 OOP 则使用对象来表达概念,并且,与 OOP 方法只能在包含它们的对象中使用不同,FP 过程得到处使用。综上所述,我们现在可以解释 Perl 为什么是混合 OOP、FP 和 PP 方法的最佳语言之一。回页首Perl 是如何将 OOP 与过程型和函数型编程结合起来的?Perl 是一种松弛的语言。它极力让程序员以他们认为方便的任何方式做他们想做的任何事。这与 Java 和 C++ 之类的语言截然不同。例如,如果程序员原本没有声明变量,Perl 乐于允许程序员自动创建变量(尽管不鼓励这样做,并且可以通过使用高度推荐的“use strict”编译指示阻止)。如果您要向自己的脚开枪,Perl 会给您十发子弹和一个激光瞄准镜,然后站在一旁鼓励您。因此,Perl 是一种非常便于滥用方法的语言。别害怕。没关系。例如,访问内部的对象数据、实时更改类和实时重定义方法都是允许的。Perl 方式是:允许程序员为了编码、调试和执行效率的目的而去打破规则。如果这有助于完成工作,那么没关系。因此,Perl 本身可能是程序员最好的朋友,也可能是最坏的敌人。如果混合 OOP、FP 和 PP 意味着打破规则,那么为什么任何人都想要混合 OOP、FP 和 PP 呢?让我们回头想想这个问题。什么是 OOP、FP 和 PP?它们只是现有的为编程团队服务的编程方法、概念集和规则集。OOP、FP 和 PP 是工具,每名程序员的首要工作就是要了解他的工具。如果一名程序员在排序散列时不能使用 FP 的 Schwartzian 变换,而是编写他自己的 Sort::Hashtable ,或者不能重用 Sys::Hostname 模块,而是编写过程代码来获得系统主机名,那么这个程序员是在浪费时间、精力和金钱,并且降低了代码质量和可靠性。 一个编程团队可能会因为它们最熟知的工具而沾沾自喜,对它们来说,这可能正是最坏的事。如果一个团队只使用象计算机编程行业那样令人冲动和充满创新的行业中所保证的可用工具的一部分,那么它在几年之后注定要变得毫无用处。程序员应该能够结合任何使工作更有效、代码更好以及使团队更具创新能力的方法。Perl 认可并鼓励这种态度。回页首OOP 的好处OOP 的好处太多,本文难以列举。正如我在前面提到的那样,有很多关于该主题的书籍。这些好处中的一小部分是:易于代码重用、代码质量的改进、一致的接口和可适应性。因为OOP 建立在类和对象的基础之上,所以重用 OO 代码意味着在需要时只需简单地导入类。至今为止,代码重用是使用 OOP 的唯一最主要原因,也是 OOP 在当今业界中的重要性和流行性日益增加的原因所在。这里有一些陷阱。例如,在当前的情况下,以前问题的解决方案可能不理想,并且文档库编制得很差,以至于理解和使用文档编制很差的库所花的时间可能与重新编写库的时间一样长。系统架构设计师的工作是看到和避免这些陷阱。使用OOP 可以提高代码质量,因为封装减少了数据毁坏(“友好之火”),而继承和多态性则减少了必须编写的新代码数量和复杂性。在代码质量和编程创新之间有一个微妙的平衡,这最好留给团队去发现,因为它完全取决于团队的构成和目的。OOP 继承和重用使得在代码中实现一致的接口变得简单,但是并不能说所有的 OO 代码都有一致的接口。程序员仍然必须遵循通用的体系结构。例如,团队应该在错误日志记录的格式和接口方面达成一致,最好通过一个允许日后扩展并且极其易用的示范模块接口来这样做。只有在那时,每名程序员才能承诺使用该接口,而不是无规则的 print 语句,因为他们会认识到在出现下一个错误日志记录函数时,学习该接口的努力不会白费。可适应性在编程中是一个有些含糊的概念。我愿意把它定义成对环境和用法更改的接受性和预见性。对于编写良好的软件来说,可适应性很重要,因为所有的软件必须随着外部世界而进化。编写良好的软件应该很容易进化。OOP 通过模块设计、改进的代码质量和一致的接口确保新操作系统或者新报告格式不要求对体系结构的核心作出根本更改,从而有助于软件的进化。回页首如何在 Perl 中使用 OOP不管您是否相信,Perl 中的 OOP 对初级和中级用户都不难,甚至对高级用户也没那么复杂。根据我们到目前为止所讨论的有关 OOP 的复杂工作方式,您可能不这么认为。然而,Perl 却乐意对程序员施加尽可能少的限制。Perl OOP 就象烤肉(恕我比喻不当)。每个人都带来自己的肉,并以自己喜爱的方式烤肉。甚至还有烤肉的团队精神也是那样,就象可以轻易在不相关的对象之间共享数据一样。我们必须采取的第一步是理解 Perl 包。包类似于 C++ 中的名称空间和 Java 中的库:象用来将数据限制在特定区域的围栏。然而,Perl 包只是为程序员提供建议。缺省情况下,Perl 不限制包之间的数据交换(尽管程序员可以通过词法变量这样做)。清单1. 包名、切换包、在包之间共享数据和包变量#!/usr/bin/perl # note: the following code will generate warnings with the -w switch, # and won‘t even compile with "use strict". It is meant to demonstrate # package and lexical variables. You should always "use strict". # pay attention to every line! # this is a global package variable; you shouldn‘t have any with "use strict" # it is implicitly in the package called "main" $global_sound = " "; package Cow; # the Cow package starts here # this is a package variable, accessible from any other package as $Cow::sound $sound = "moo"; # this is a lexical variable, accessible anywhere in this file my $extra_sound = "stampede"; package Pig; # the Pig package starts, Cow ends # this is a package variable, accessible from any other package as $Pig::sound $Pig::sound = "oink"; $::global_sound = "pigs do it better"; # another "main" package variable # we‘re back to the default (main) package package main; print "Cows go: ", $Cow::sound; # prints "moo" print "\nPigs go: ", $Pig::sound; # prints "oink" print "\nExtra sound: ", $extra_sound; # prints "stampede" print "\nWhat‘s this I hear: ", $sound; # $main::sound is undefined! print "\nEveryone says: ", $global_sound; # prints "pigs do it better" 请注意,可以在所有三个包(“main”、“Pig”和“Cow”)中访问文件作用域内的词法变量 $extra_sound ,因为在该示例中它们是在同一文件中定义的。通常,每个包在它自己文件内部定义,以确保词法变量为该包所私有。这样就可以实现封装。(有关详细信息,请运行“ perldoc perlmod”。) 接下来,我们要将包与类关联。就 Perl 而言,类只是一个奇特的包(相反,对象由 bless() 函数特别创建)。同样,Perl 对 OOP 规则实施得不是很严格,以便程序员不为其所约束。 new() 方法是类构造器的惯用名称(尽管按照 Perl 惯有的不严格方式,您可以使用任意名称)。当将类实例化成对象时都要调用它。 清单2. barebones 类#!/usr/bin/perl -w package Barebones; use strict; # this class takes no constructor parameters sub new my $classname = shift; # we know our class name bless , $classname; # and bless an anonymous hash 1; 可以通过将清单 2 中的代码放入任何目录内名为 Barebones.pm 的文件中,然后在该目录中运行以下命令来测试该代码(这表示:“在库路径中包括当前目录,使用 Barebones 模块,然后创建一个新的 Barebones 对象”):perl -I. -MBarebones -e ‘my $b = Barebones->new()‘ 例如,可以在 new() 方法中放入 print 语句,以便看到 $classname 变量所拥有的内容。 如果调用 Barebones::new() 而不是 Barebones->new() ,类名将不会传递到 new() 。换句话说, new() 将不作为构造器,而只是普通的函数。 您可能要问:为什么需要传入 $classname 。为什么不直接用 bless , "Barebones"; ?因为继承的缘故,这个构造器可能被一个从 Barebones 继承、但名称却不是 Barebones 的类调用。您可能正在用错误的名称享有错误的事,而在 OOP 中,那是个坏主意。 除了new() 之外,每个类都需要成员数据和方法。定义它们就象编写几个过程一样简单。 清单3. 带有成员数据和方法的类#!/usr/bin/perl -w package Barebones; use strict; my $count = 0; # this class takes no constructor parameters sub new my $classname = shift; # we know our class name $count++; # remember how many objects bless , $classname; # and bless an anonymous hash sub count my $self = shift; # this is the object itself return $count; 1; 可以用以下命令测试该代码:perl -I. -MBarebones -e ‘my $b = Barebones->new(); Barebones->new(); print $b->count‘ 您应该得到 ‘2‘ 这个结果。构造器被调用两次,它修改词法变量( $count),该变量被限制在 Barebones 包的作用域,而 不是每个Barebones 对象的作用域。应该将对象本身范围内的数据存储在对象本身中。在 Barebones 的示例中,被享有成对象的是匿名散列。请注意我们怎样才能在每次调用该对象的方法时访问该对象,因为对该对象的引用是传递给那些方法的第一个参数。 有几个特殊的方法,例如 DESTROY() 和AUTOLOAD(),Perl 在某些条件下会自动调用它们。 AUTOLOAD() 是用来允许动态方法名称的全捕获(catch-all)方法。 DESTROY() 是对象析构器,但是除非您确实非常非常需要,否则不应该使用它。在 Perl 中使用析构器通常表明您还在象 C/C++ 程序员那样考虑问题。 让我们看一下继承。在 Perl 中通过更改 @ISA 变量来这样做。您只需将一个类名表赋值给该变量即可。就是这样。您可以在 @ISA 中放入任何东西。您可以使您的类成为 Satan 的子类。Perl 不在乎(尽管您的牧师、部长、教长、犹太学者等可能在乎)。 清单4. 继承#!/usr/bin/perl -w package Barebones; # add these lines to your module‘s beginning, before other code or # variable declarations require Animal; # the parent class @ISA = qw(Animal); # announce we‘re a child of Animal # note that @ISA was left as a global default variable, and "use # strict" comes after its declaration. That‘s the easiest way to do it. use strict; use Carp; # make your new() method look like this: sub new my $proto = shift; my $class = ref($proto) || $proto; my $self = $class->SUPER::new(); # use the parent‘s new() method bless ($self, $class); # but bless $self (an Animal) as Barebones 1; 这些是 Perl 中 OOP 的最基本知识。Perl 语言中还有很多您应该探索的知识。人们已经撰写了很多有关这一主题的书籍。如果想阅读的话,请参考 参考资料。 回页首h2xs:您最好的新朋友您不想拥有一个可以为您编写 Perl 类、还可以编写文档(POD)框架并且通常可以通过正确地完成这些事而使您的生活轻松一些的工具吗?Perl 正好带有这种工具: h2xs。 别忘了使用几个重要标志:“ -A -n Module”。利用这些标志,h2xs 将生成一个名为“Module”、且里面全是有用文件的框架目录。这些文件是: Module.pm ,模块本身,带有已经编写好的框架文档。 Module.xs ,用于将您的模块与 C 代码链接。(有关详细信息,请运行“ perldoc perlxs”。) MANIFEST ,用于打包的文件列表。 test.pl ,框架测试脚本。 Changes ,对该模块所做更改的日志。 Makefile.PL,makefile 生成器(用“ perl Makefile.PL ”运行它。) 您无需使用所有这些文件,但是在您确实需要它们时知道它们在那里是很好的。本回答被提问者采纳

以上是关于OOP 4-6次题目集总结的主要内容,如果未能解决你的问题,请参考以下文章

OOP课程题目集第二次总结

题目集4-6次总结

题目集4~6总结心得

Java第二次作业总结

OOP第四次到第六次作业总结

PTA题目集4~6的总结