第4-6次OOP作業總結

黄裕涛發表於2024-06-09

一、前言
1.第四次作業(答題判題程式4)
這次作業題目在原先的題型型別上新增了多選題和填空題,考慮到和原來的題目具有相同的屬性,我果斷選擇使用當時剛學的繼承來描述這兩種新題型資訊,但是新題型的分數計算比較複雜,只好多用幾個if語句來加強判斷了。新增的多名同學多張卷,以及同一個同學對不同試卷需要排序,我選擇先按學號排序,再重新遍歷並對於學號相同的試卷之間進行試卷號的排序,雖然時間的複雜度有點高,但也不失為可行的笨辦法,否則用hashmap可以有更好的方法。這次作業的難度適中,但不好拿高分,主要在多張試卷的排序上,數量少點還好說,多起來我的排序便不管用了,其次便是沒有考慮到未作答以及白卷的情況。
2.第五次作業(家居強電電路模擬程式-1)
這次作業著重考察繼承和多型的使用,電器間的關係複雜又自成一脈,我將其總體分為電路、控制器、受控制器。在理清物件關係上時間花了不少,本來根據電器的屬性描述書寫了不少成員變數和方法,後面直接看到具體輸入資訊發現多餘了,索性直接根據題目輸入資訊設定變數。這三個類父類擁有一個共同的父類ElecLoad,它具有名字、輸入輸出電壓及相應的編號等基礎屬性。不同類之間具有相同或相似的屬性較多,因此關係相對明確,能夠相對較完善的得到一個初步的認識。這次的作業比較容易,總體分為三個步驟,資訊的輸入讀取,電壓的計算,電器的資訊輸出,所有步驟在主方法便可完成,不是很複雜。甚至對正規表示式的需求也不是很大。唯一的難點便是對於輸出時要按照特定的順序,直至這次作業的截至都沒相出一個較好的方法。
3.第六次作業(家居強電電路模擬程式-2)
這次作業雖然只在上一次的基礎上幹路上迭代了一個並聯電路,但不管是程式碼還是步驟數都是激增,更為要命的是測試點的提示不在開放,而樣例中只有看看三個,且所設計的範圍也是比較小的。因此這意味者我們需要自己設計各種可能且具有代表性的樣例,這又在無形中增添了難度。同時為了解決上次作業遺留的排序問題,我特意建立了一個Show類用來備份讀入的物件資訊,一方面不影響原先各種操作,另一方面增加對不同物件的針對性操作,如同型別物件排序,輸出等。本次主要涉及知識點變化不大,主要增加的類之間的關係,題目難度激增,過程更是又原先的3步變成了輸入->控制器操作->判斷並聯電路斷聯情況->計算電阻->計算電壓->排序->輸出。如果採用傳統列表遍歷的方式將面臨多層巢狀的問題。
二、設計與分析
1.先看一下程式碼的複雜度

method CogC ev(G) iv(G) v(G)
Anspaper.addSqa(String) 2.0 1.0 3.0 3.0
Delete.addDelete(String, Paper) 7.0 4.0 5.0 5.0
Main.anspapername(ArrayList, Student) 6.0 1.0 4.0 4.0
Main.endscore(Anspaper) 1.0 1.0 2.0 2.0
Main.ismanfen(ArrayList) 5.0 1.0 4.0 4.0
Main.main(String[]) 9.0 1.0 9.0 9.0
Main.pinfen(ArrayList, ArrayList, Paper, PaperZ, PaperK) 19.0 8.0 8.0 9.0
Main.sortanspaper(ArrayList) 16.0 1.0 8.0 8.0
Main.sortpaperfen(ArrayList) 6.0 1.0 4.0 4.0
Paper.addQA(String) 1.0 1.0 2.0 2.0
Paper.searchqa(int, int, Anspaper, int) 27.0 6.0 8.0 8.0
Paperfen.addFenzhi(String) 2.0 1.0 3.0 3.0
PaperK.addQA(String) 1.0 1.0 2.0 2.0
PaperK.searchqa(int, int, Anspaper, int) 38.0 9.0 9.0 9.0
PaperZ.addQA(String) 1.0 1.0 2.0 2.0
PaperZ.searchqa(int, int, Anspaper, int) 65.0 9.0 13.0 13.0
Student.addStu(String) 1.0 1.0 2.0 2.0

可以看到其中PaperZ.searchqa(int, int, Anspaper, int)方法的複雜度達到了驚人的65,這是因為套用了4重迴圈,這也側面反映了傳統的使用ArrayList來進行查詢操作時的諸多不便,並且除錯的過程也變得異常艱難

class OCavg OCmax WMC
Anspaper 3.0 3.0 3.0
Delete 5.0 5.0 5.0
Fenzhi 0.0
Main 5.7 9.0 40.0
Paper 5.0 8.0 10.0
Paperfen 3.0 3.0 3.0
PaperK 5.5 9.0 11.0
PaperZ 7.5 13.0 15.0
QA 0.0
Sqa 0.0
Stu 0.0
Student 2.0 2.0 2.0

這是類關係圖

PaperK和PapaerZ與Paper是繼承關係,因為他們的屬性相同,只有評分標準不同,因此只需重寫評分方法和資訊的輸入就行
2.先看複雜度

method CogC ev(G) iv(G) v(G)
Alspeed.Alspeed() 0.0 1.0 1.0 1.0
Alspeed.Alspeed(double, int) 2.0 1.0 1.0 3.0
Alspeed.display() 0.0 1.0 1.0 1.0
Alspeed.setDang(String) 2.0 1.0 1.0 3.0
Bai.Bai() 0.0 1.0 1.0 1.0
Bai.display() 0.0 1.0 1.0 1.0
Bai.getBright() 3.0 1.0 1.0 3.0
BeControler.BeControler() 0.0 1.0 1.0 1.0
Bus.addElec(ElecLoad) 0.0 1.0 1.0 1.0
Bus.Bus() 0.0 1.0 1.0 1.0
Controler.getOut() 0.0 1.0 1.0 1.0
ElecLoad.display() 0.0 1.0 1.0 1.0
ElecLoad.setDang(String) 0.0 1.0 1.0 1.0
Fan.display() 0.0 1.0 1.0 1.0
Fan.Fan() 0.0 1.0 1.0 1.0
Fan.getRunspeed() 4.0 1.0 1.0 4.0
Fenspeed.display() 0.0 1.0 1.0 1.0
Fenspeed.Fenspeed() 0.0 1.0 1.0 1.0
Fenspeed.Fenspeed(double, int) 0.0 1.0 1.0 1.0
Fenspeed.setDang(String) 6.0 1.0 2.0 5.0
Lamp.Lamp() 0.0 1.0 1.0 1.0
Main.main(String[]) 70.0 1.0 24.0 25.0
Of.display() 2.0 1.0 2.0 2.0
Of.getOut() 1.0 2.0 1.0 2.0
Of.Of() 0.0 1.0 1.0 1.0
Of.setDang(String) 2.0 1.0 1.0 2.0
Ri.display() 0.0 1.0 1.0 1.0
Ri.getBright() 2.0 1.0 1.0 2.0
Ri.Ri() 0.0 1.0 1.0 1.0
Total 94.0 30.0 54.0 70.0
Average 3.2 1.0 1.8 2.4
class OCavg OCmax WMC
Main 25.0 25.0 25.0
Fenspeed 2.0 5.0 8.0
Of 1.75 2.0 7.0
Fan 1.7 3.0 5.0
Alspeed 1.5 2.0 6.0
Bai 1.3 2.0 4.0
Ri 1.3 2.0 4.0
BeControler 1.0 1.0 1.0
Bus 1.0 1.0 2.0
Controler 1.0 1.0 1.0
ElecLoad 1.0 1.0 2.0
Lamp 1.0 1.0 1.0
Pin 0.0
Total 66.0
Average 2.2 3.8 5.0

可以看到其他類的複雜度較低,主要都是集中在主方法中,其中的輸入一塊稍顯臃腫
類圖關係如下

可以看到所有類之間關係密切,三個開關,三個用電器
3.程式碼複雜度

method CogC ev(G) iv(G) v(G)
Alspeed.Alspeed() 0.0 1.0 1.0 1.0
Alspeed.Alspeed(double, int) 2.0 1.0 1.0 3.0
Alspeed.display() 0.0 1.0 1.0 1.0
Alspeed.setDang(String) 2.0 1.0 1.0 3.0
Alspeed.setV() 0.0 1.0 1.0 1.0
Bai.Bai() 0.0 1.0 1.0 1.0
Bai.Bai(double, String) 0.0 1.0 1.0 1.0
Bai.display() 0.0 1.0 1.0 1.0
Bai.getBright() 6.0 2.0 1.0 4.0
Bbus.caculate() 5.0 1.0 4.0 5.0
Bbus.setV(double, double, double) 7.0 1.0 4.0 5.0
BeControler.BeControler() 0.0 1.0 1.0 1.0
BeControler.BeControler(double, String) 0.0 1.0 1.0 1.0
Bus.addElec(ElecLoad) 0.0 1.0 1.0 1.0
Bus.Bus() 0.0 1.0 1.0 1.0
Controler.display() 0.0 1.0 1.0 1.0
Controler.getOut() 0.0 1.0 1.0 1.0
Controler.setV() 0.0 1.0 1.0 1.0
D.D() 0.0 1.0 1.0 1.0
D.D(double, String) 0.0 1.0 1.0 1.0
D.display() 0.0 1.0 1.0 1.0
D.getRunspeed() 7.0 2.0 1.0 6.0
ElecLoad.caculate() 0.0 1.0 1.0 1.0
ElecLoad.display() 0.0 1.0 1.0 1.0
ElecLoad.setDang(String) 0.0 1.0 1.0 1.0
ElecLoad.setV() 0.0 1.0 1.0 1.0
Fan.display() 0.0 1.0 1.0 1.0
Fan.Fan() 0.0 1.0 1.0 1.0
Fan.Fan(double, String) 0.0 1.0 1.0 1.0
Fan.getRunspeed() 0.0 1.0 1.0 1.0
Fbus.caculate() 6.0 4.0 3.0 4.0
Fbus.setV(double) 10.0 1.0 5.0 5.0
Fenspeed.display() 0.0 1.0 1.0 1.0
Fenspeed.Fenspeed() 0.0 1.0 1.0 1.0
Fenspeed.Fenspeed(double, int) 0.0 1.0 1.0 1.0
Fenspeed.setDang(String) 6.0 1.0 2.0 5.0
Fenspeed.setV() 0.0 1.0 1.0 1.0
Lamp.Lamp() 0.0 1.0 1.0 1.0
Lamp.Lamp(double, String) 0.0 1.0 1.0 1.0
Luo.display() 0.0 1.0 1.0 1.0
Luo.getRunspeed() 11.0 2.0 1.0 9.0
Luo.Luo() 0.0 1.0 1.0 1.0
Luo.Luo(double, String) 0.0 1.0 1.0 1.0
Main.main(String[]) 137.0 15.0 52.0 53.0
Of.display() 2.0 1.0 2.0 2.0
Of.Of() 0.0 1.0 1.0 1.0
Of.setDang(String) 2.0 1.0 1.0 2.0
Of.setV() 0.0 1.0 1.0 1.0
Ri.display() 0.0 1.0 1.0 1.0
Ri.getBright() 5.0 2.0 1.0 3.0
Ri.Ri() 0.0 1.0 1.0 1.0
Ri.Ri(double, String) 0.0 1.0 1.0 1.0
Show.display() 21.0 1.0 15.0 15.0
Show.Show() 0.0 1.0 1.0 1.0
Show.sort(ArrayList) 10.0 1.0 5.0 5.0
Total 239.0 76.0 138.0 168.0
Average 4.3 1.4 2.5 3.1

複雜度依然主方法高,顯然計算程式碼集中在此,因為我將計算電阻和判斷斷聯情況放在一起,導致有點層次不分,故而增加的複雜度。

class OCavg OCmax WMC
Main 51.0 51.0 51.0
Show 7.0 15.0 21.0
Bbus 4.5 5.0 9.0
Fbus 4.5 5.0 9.0
Luo 2.25 6.0 9.0
D 2.0 5.0 8.0
Fenspeed 1.8 5.0 9.0
Bai 1.5 3.0 6.0
Of 1.5 2.0 6.0
Ri 1.5 3.0 6.0
Alspeed 1.4 2.0 7.0
BeControler 1.0 1.0 2.0
Bus 1.0 1.0 2.0
Controler 1.0 1.0 3.0
ElecLoad 1.0 1.0 4.0
Fan 1.0 1.0 4.0
Lamp 1.0 1.0 2.0
Pin 0.0
Total 158.0
Average 2.9 6.4 8.8

三、踩坑心得
1.為了將題目要求的資訊讀取並儲存,我創的類有點過多了,有好幾個是可以整合到一起的,這樣既可以減少不必要的遍歷,也可以便於除錯時資料的檢視,比如幾個問題與答案完全可以統一。其次這次作業出現多次的根據某個變數在查詢另一變數並操作的情況,使用ArrayList儲存資訊每次都要遍歷才能找到,時間複雜度高,所需要的迴圈巢狀多,並不適用於本次題目的場景。因此在理清物件的關係後,選擇一個合適的list將有助於後續程式碼的書寫和思考。

可以看到多重迴圈和if語句使得可讀性有所降低,修改起來也頗為麻煩
2.輸入使用正則和String類的一些方法進行資訊的甄別,但對於類似[VCC L1-1]一塊的處理並不妥善,我想的是透過區分左右資訊是不是“VCC”和“GND”來選擇新添的物件,並同時確定電路的輸入端和輸出端以及給予相應的電壓,如語句bus.mainbus.get(bus.mainbus.size()-1).in.v=220;

然而未考慮到List中是否有元素,好在本次作業測試點並未有這方面的考量,但這為下次作業我整的我崩潰的清一色的“非零返回”埋下伏筆。不過好在這次的槽點不算多,一方面畢竟是這種題型的作業的第一次,還未進行迭代,故而需考慮的地方較少,其次題目所需要的計算較少,步驟亦是如此,只需簡單的遍歷操作和輸出即可。
3.這次作業沒有將各個步驟拆分為多個方法進行,在進行計算電阻和判斷斷聯情況為將其拆分,導致有點繞和層次不分,Show類的建立極大的簡化了我的排序過程,

並且可以更有針對性的解決的列表遍歷時的多重巢狀問題,畢竟修改前我需要重迴圈的操作一下便做到了。

對於以往需要多重迴圈考慮在幹路還是在並聯的支路上,如今只需到相應的型別的列表中尋找
四、改進建議
1.(1)可以使用hashmap重新建立資訊間的聯絡,這樣在根據已知資訊進行查詢時會方便;
(2)重新審視類的關係,使用繼承來簡化屬性和方法;
(3)減少多重迴圈的使用,增加更多註釋來方便解讀步驟;
2.(1)更改輸入時[]內資訊的讀取,原先的程式碼並未考慮到列表集合為空的特殊情況;
(2)改進電器的輸出排序相關的方法,可以透過建立對應的類的列表專門儲存同一類物件的資訊,從而更好的進行排序並輸出;
3.(1)分步進行操作,建立多個方法各司其職,增強可讀性,同時也不會顯得主方法頭重腳輕;
(2)輸入部分過於臃腫,全是if的條件語句用於區分情況,不利於除錯和閱讀;
(3)幹路和並聯的支路具有相同的屬性,應屬於同一型別,應將他們統一到一個類中;
五、總結
相較於上次對於正規表示式的考察,這三次注重於對類的關係和繼承多型的理解和使用。透過這三次作業的多次實踐我進一步理解和掌握了繼承和多型的概念和用法,同時對類間關係有了進一步的理解,也更加深入的明白的hashmap與ArrayList的優劣和各自的適用場景。
建議:建議PTA作業最後兩天開放測試點的提示;