1. 程式人生 > 其它 >blog總結3

blog總結3

  在完成三次題目集後,我覺得有必要對著次的練習進行一次總結。這次的練習的主要圍繞類的繼承、多型的使用方法以及介面的應用。java的學習主要需要相關題目的大量練習,如接下來所要提到到的四個比較典型的題目。

  在題目集07的7-1題中,題目要求對圖形卡片進行排序的小遊戲。大致瞭解一下該題的主要內容:考慮一款適合於小學生的卡片(Card)排序遊戲,其規則為隨機發放一些卡片給學生,卡片分為 四種形狀:圓形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid),並給出各種卡片的相應引數,要求學生能夠迅速求出各卡片的面積大小然後將卡片按照其面積值從大到小進行排 序同時求出所有卡片的面積之和。圖形類層次結構,本次作業要求對卡片排序時使用 Comparable 介面, 即 Card 類需要實現 Comparable 介面中的 CompareTo()方法。在瞭解了題目的大致要求後,可以得到相關類圖,本程式僅用於為學生所玩的遊戲提供正確答案的功能,即根據學生得到的卡片種類與數量,給出 排序前和排序後的卡片順序,同時給出所有卡片的面積之和。在寫該程式碼時,可以參考類圖的思路得到程式碼:

  程式碼輸入輸出規則 ①輸入規則 首先,在一行上輸入一串數字(1~4,整數),其中,1 代表圓形卡片,2 代表矩形卡片,3 代表 三角形卡片,4 代表梯形卡片。各數字之間以一個或多個空格分隔,以“0”結束。例如: 1 3 4 2 1 3 4 2 1 3 0 ,然後根據第一行數字所代表的卡片圖形型別,依次輸入各圖形的相關引數,例如:圓形卡片需要 輸入圓的半徑,矩形卡片需要輸入矩形的寬和長,三角形卡片需要輸入三角形的三條邊長,梯形需要 輸入梯形的上底、下底以及高。各資料之間用一個或多個空格分隔。 ②輸出規則 : 如果圖形數量非法(小於 0)或圖形屬性值非法(數值小於 0 以及三角形三邊不能組成三 角形),則輸出“Wrong Format”。如果輸入合法,則正常輸出,所有數值計算後均保留小數點後兩位即可。輸出內容如下: 排序前的各圖形型別及面積,格式為“圖形名稱 1:面積值 1 圖形名稱 2:面積值 2 …圖形名稱 n:面積值 n ”,注意,各圖形輸出之間用空格分開,且輸出最後存在一個用於分隔的空格;排序後的各圖形型別及面積,格式同排序前的輸: 所有圖形的面積總和,格式為“Sum of area:總面積值。

輸入示例 1: 1 5 3 2 0 輸出示例 1: Wrong Format 輸入示例 2: 4 2 1 3 0 3.2 2.5 0.4 2.3 1.4 5.6 2.3 4.2 3.5 輸出示例 2: The original list: Trapezoid:1.14 Rectangle:3.22 Circle:98.52 Triangle:4.02 The sorted list: Circle:98.52 Triangle:4.02 Rectangle:3.22 Trapezoid:1.14 Sum of area:106.91 輸入示例 3: 4 2 1 3 0 3.2 2.5 0.4 2.3 1.4 5.6 2.3 4.2 8.4 輸出示例 3: Wrong Format。

  瞭解了題目的要求和所需要的的功能後,接下來就是對程式碼的分析。該題的難度適中,在學習了繼承的基礎下就可以把正確的程式碼寫出來。該題可以建立七個類,卡片類:Triangle、Circle、Traperoid、Rectangle剛好對應三種卡片。再寫一個它們的父類Shape類。我認為寫該題的出入口在於知道運用繼承以及建立ArrayList類:ArrayList<Integer> list = new ArrayList<Integer>(),這樣可以將輸入的整形數字放入list中:list.add(num)。再將Shape類放入Card類中,這樣的話可以再建立一個ArrayLiat類:ArrayList < Card > cardList=new ArrayList<Card>();將Card類放入ArrayList中,這樣的話在list的各個元素中,若輸入的數字是1,則

for(int i=0;i<list.size();i++)
        {
            if(list.get(i)==1)
            {
                double radius=Main.input.nextDouble();
                Circle circle=new Circle(radius);
                Card card=new Card(circle);
                card.getShape().setName("Circle");
                cardList.add(card);
            }

若list中的元素是2、3、4程式碼與上類似。在這段程式碼中規定了圖形的基本資料,再將這個新建立的卡放片物件放入Card card=new Card(circle)。card.getShape().setName("Rectangle");這段程式碼中充分體現了繼承的優點:子類可以呼叫父類中的某些方法。在這題中我還學會了如何簡便的對它們的面積大小進行排序:這需要在程式碼的開頭進行宣告:import java.util.Collections。

public void toSort() {
        for(int m=0;m<cardList.size();m++)
            for(int j=m+1;j<cardList.size();j++)
            {
                if(cardList.get(m).getShape().getArea()<cardList.get(j).getShape().getArea())
                    Collections.swap(cardList, m, j);
            }
        
        
    }

後面的程式碼內容主要是寫各個類:shape類、Rectangle 類等

class Rectangle extends Shape{
    private double length;
    private double width;
    Rectangle (double length ,double width){
        this.width=width;
        this.length=length;
    }
    public double getArea() {
        return width*length;
    }
    public boolean vaildate() {
        if(width>0&&length>0)
        return true;
        else
            return false;
    }
    
}

在寫繼承時,最看重的是程式碼的封裝性。例如:在主函式中 if(!dealCardList.validate()) 中的validate方法 在dealCardList中

public boolean validate() {
        for(int i=0;i<cardList.size();i++)
            {
            if(!cardList.get(i).getShape().vaildate())
                    return false;
            }
        return true;
    }

該方法中的validate中包含了各個形狀的類中的判斷類,這充分體現了程式碼的封裝性和完整性。該程式碼的總的複雜度為6,複雜度較低。如下圖所示:

  該題與上一題的結構差不多,但題目要求的輸出不一樣,所以該題的難度比上一題更難一點,但寫的內容大部分還是相同的。

    public double caulateAllArea() {
        double[] sum = new double[4];
        for(int j=0;j<cardList.size();j++) {
            if(cardList.get(j).getShape() instanceof Circle)
                sum[0] += cardList.get(j).getShape().getArea();
            if(cardList.get(j).getShape() instanceof Traperoid)
                sum[1] += cardList.get(j).getShape().getArea();
            if(cardList.get(j).getShape() instanceof Triangle)
                sum[2] += cardList.get(j).getShape().getArea();
            if(cardList.get(j).getShape() instanceof Rectangle)
                sum[3] += cardList.get(j).getShape().getArea();
        }
        int max = 0;
        for(int i = 0; i < 4; i ++)
            if(sum[max] < sum[i])
                max = i;
        return sum[max];

    }

   得到以上類圖:

由程式碼可的該程式碼的複雜度:

故該程式碼的複雜度為9,沒有超過11,寫的還算簡單。這裡面還用到了物件轉換和instanceof操作符,總是可以將一個子類的例項轉換為一個父類的變數,稱為向上轉換,因為子類的例項總是他父類的例項。當把一個父類的例項轉換為它的子類變數時,必須使用轉換標記進行顯式轉換。如果父類物件不是子類的一個例項,就會出現一個執行時異常。

    題目集8的atm機類改造設計,就是編寫一個銀行 ATM 機的模擬程式,能夠完成使用者的存款、取款以及查詢餘額功能。該題比較有難度,但還是有比較清晰的思路。在該題中我學會了如何使用ArrayList類,一級一級的將類放入。先是寫銀聯,如何銀聯裡包含了銀行,銀行裡又有賬戶和atm,賬戶裡有銀行卡,此外還有使用者,這樣根據它們之間的關係一層層寫下去。

class UnionPay {
    private ArrayList<Bank> bankList = new ArrayList<Bank>();

    public UnionPay() {
        super();
        // TODO Auto-generated constructor stub
    }

    public UnionPay(ArrayList<Bank> bankList) {
        super();
        this.bankList = bankList;
    }

    public ArrayList<Bank> getBankList() {
        return bankList;
    }

    public void setBankList(ArrayList<Bank> bankList) {
        this.bankList = bankList;
    }
    
    public void addBank(Bank bank) {
        this.bankList.add(bank);
    }
    
    public void removeBank(Bank bank) {
        this.bankList.remove(bank);
    }    
}

複雜度為8,說明寫的程式碼不會太複雜。其部分程式碼如下所示:

public class Bank {
    private String name;
    private ArrayList<Atm> listAtm = new ArrayList<Atm>();
    private ArrayList<User> listUser = new ArrayList<User>();
    public Bank() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Bank(String name, ArrayList<Atm> listAtm, ArrayList<User> listUser) {
        super();
        this.name = name;
        this.listAtm = listAtm;
        this.listUser = listUser;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public ArrayList<Atm> getListAtm() {
        return listAtm;
    }
    public void setListAtm(ArrayList<Atm> listAtm) {
        this.listAtm = listAtm;
    }
    public ArrayList<User> getListUser() {
        return listUser;
    }
    public void setListUser(ArrayList<User> listUser) {
        this.listUser = listUser;
    }
    public void listAtmAdd(Atm atm) {
        listAtm.add(atm);
    }
    public void listUserAdd(User user) {
        listUser.add(user);
    }
}

該題充分利用了ArrayList的優點,ArrayList的大小是靈活的,所以無需提前給定它的大小。當建立一個數組時,它的大小必須給定。

mport java.util.ArrayList;
class Unionpay {
    
     private ArrayList<Bank> listBank = new ArrayList<Bank>();
     
     public Unionpay() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Unionpay(ArrayList<Bank> listBank) {
        super();
        this.listBank = listBank;
    }

    public ArrayList<Bank> getListBank() {
        return listBank;
    }

    public void setListBank(ArrayList<Bank> listBank) {
        this.listBank = listBank;
    }
    
    public void listBankAdd(Bank bank) {
        listBank.add(bank);
    }
       
}

      題目集9的atm的程式碼大部分的思路與上一題差不多,但它增加了一些要求,比如說銀行賬戶分為借記賬戶和貸記賬戶兩種,其中,借記賬戶不能夠透支 取款,而貸記賬戶可以透支取款(可能需要支付手續費),此外。根據賬戶 的不同,銀行卡一般分為借記卡(針對借記賬戶)和信用卡(針對貸記賬戶) 兩類。且允許跨行辦理相關業 務(例如在中國建設銀行的 ATM 機上使用中國工商銀行的銀行卡進行業務操作),故又需要在原來程式碼的基礎上新增一些新的功能。

程式碼寫的比較長,但總的複雜度就5。相關程式碼內容如下:

public class CreditAccount extends Account{
    private double facility = 0;
    
    public CreditAccount() {
        super();
        // TODO Auto-generated constructor stub
    }

    public CreditAccount(String accountNO, double balance, User user, Bank bank, double facility) {
        super(accountNO, balance, user, bank);
        // TODO Auto-generated constructor stub
        this.facility = facility;
    }

    public double getFacility() {
        return facility;
    }

    public void setFacility(double facility) {
        this.facility = facility;
    }
    
}
public class CreditWithdraw extends Withdraw {
    

    public CreditWithdraw() {
        super();
        // TODO Auto-generated constructor stub
    }

    public CreditWithdraw(ATM atm, Account account, double b1, double b2) {
        super(atm, account, b1, b2);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void withdraw() {
        // TODO Auto-generated method stub
        double balance = getAccount().getBalance();
        if(balance > 0 && balance < getB1()) {
            setB2(getB2() + (getB1() - balance) * 0.05); 
        }
        else if(balance < 0) {
            setB2(getB2() + getB1() * 0.05);
        }
        balance = balance - getB1() - getB2();
        getAccount().setBalance(balance);
    }

}

系統的測試用例均採用題目中的資料,且所有卡號密碼預設為“88888888”, 初始餘額均為 10000 元,手續費預設均從銀行卡所對應的賬戶中自動扣除。跨行業務手續費收取比例由 ATM 機隸屬銀行決定,例如,使用者手持中國 工商銀行的銀行卡在中國建設銀行的 ATM 上進行取款操作,則手續費收取比例為 中國建設銀行的相應比例,按初始化資料中的規定為取款金額的 2%。跨行查詢餘額不收取手續費,透支取款手續費由中國銀聯統一規定為 5%,最大透支金額均為 50000 元。

例如如下程式碼:

public class DebitWithdraw extends Withdraw {
    
    public DebitWithdraw() {
        super();
        // TODO Auto-generated constructor stub
    }

    public DebitWithdraw(ATM atm, Account account, double b1, double b2) {
        super(atm, account, b1, b2);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void withdraw() {
        double balance = getAccount().getBalance();
        balance = balance - this.getB1() - this.getB2(); 
        getAccount().setBalance(balance);
    }

}
public class CreditWithdraw extends Withdraw {
    

    public CreditWithdraw() {
        super();
        // TODO Auto-generated constructor stub
    }

    public CreditWithdraw(ATM atm, Account account, double b1, double b2) {
        super(atm, account, b1, b2);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void withdraw() {
        // TODO Auto-generated method stub
        double balance = getAccount().getBalance();
        if(balance > 0 && balance < getB1()) {
            setB2(getB2() + (getB1() - balance) * 0.05); 
        }
        else if(balance < 0) {
            setB2(getB2() + getB1() * 0.05);
        }
        balance = balance - getB1() - getB2();
        getAccount().setBalance(balance);
    }

}

AraaayList類是一個泛型類,在寫該題程式碼時,arraylist類發揮了重要作用。