ο缶幊倘腴T(mén)(一):認(rèn)識(shí)類(lèi)與對(duì)象)
1. 為什么需要面向?qū)ο笤诿嫦蜻^(guò)程編程中我們把程序拆成一個(gè)個(gè)函數(shù)數(shù)據(jù)與操作數(shù)據(jù)的邏輯往往是分離的。隨著項(xiàng)目變復(fù)雜這種方式會(huì)帶來(lái)兩個(gè)問(wèn)題數(shù)據(jù)的狀態(tài)散落在各處難以維護(hù)代碼復(fù)用困難修改一處可能影響全局。面向?qū)ο驩bject-Oriented ProgrammingOOP的核心思想是把數(shù)據(jù)和對(duì)數(shù)據(jù)的操作捆綁在一起用“對(duì)象”來(lái)模擬現(xiàn)實(shí)世界的事物。這樣寫(xiě)出來(lái)的代碼更接近人類(lèi)的思維方式也更容易維護(hù)和擴(kuò)展。本文是面向?qū)ο笙盗械牡谝黄覀儚淖罨A(chǔ)的兩個(gè)概念開(kāi)始類(lèi)和對(duì)象。2. 類(lèi)與對(duì)象的關(guān)系2.1 什么是類(lèi)類(lèi)是對(duì)象的模板或藍(lán)圖它描述了一類(lèi)事物共有的屬性和行為。屬性描述事物的特征對(duì)應(yīng)代碼中的變量行為描述事物能做什么對(duì)應(yīng)代碼中的方法。2.2 什么是對(duì)象對(duì)象是類(lèi)的具體實(shí)例。類(lèi)是抽象的對(duì)象是具體的。以“學(xué)生”為例Student是類(lèi)它描述了所有學(xué)生都有姓名、學(xué)號(hào)等屬性以及上課、考試等行為具體某個(gè)學(xué)生如“張三”就是一個(gè)對(duì)象。用一句話(huà)總結(jié)類(lèi)是模板對(duì)象是按模板造出來(lái)的具體實(shí)例。2.3 代碼示例下面用 Java 定義一個(gè)最簡(jiǎn)單的學(xué)生類(lèi)并創(chuàng)建兩個(gè)對(duì)象publicclassStudent{// 屬性Stringname;StringstudentId;// 行為publicvoidstudy(){System.out.println(name 正在學(xué)習(xí));}}創(chuàng)建對(duì)象并使用publicclassMain{publicstaticvoidmain(String[]args){// 使用 new 關(guān)鍵字創(chuàng)建對(duì)象StudentzhangsannewStudent();zhangsan.name張三;zhangsan.studentId2024001;zhangsan.study();StudentlisinewStudent();lisi.name李四;lisi.studentId2024002;lisi.study();}}運(yùn)行結(jié)果張三 正在學(xué)習(xí) 李四 正在學(xué)習(xí)可以看到同一個(gè)類(lèi)可以創(chuàng)建出多個(gè)對(duì)象每個(gè)對(duì)象都有自己獨(dú)立的數(shù)據(jù)。3. 封裝把數(shù)據(jù)保護(hù)起來(lái)上面的寫(xiě)法有一個(gè)明顯的問(wèn)題name和studentId被聲明為公開(kāi)的外部代碼可以隨意修改。比如zhangsan.name;用面向?qū)ο蟮牡诙€(gè)重要概念——封裝可以解決這個(gè)問(wèn)題。封裝的思路是把屬性設(shè)置為私有private提供公開(kāi)的getter和setter方法在方法里做數(shù)據(jù)校驗(yàn)。改寫(xiě)后的Student類(lèi)publicclassStudent{// 屬性私有化privateStringname;privateStringstudentId;publicStringgetName(){returnname;}publicvoidsetName(Stringname){if(namenull||name.isEmpty()){thrownewIllegalArgumentException(姓名不能為空);}this.namename;}publicStringgetStudentId(){returnstudentId;}publicvoidsetStudentId(StringstudentId){this.studentIdstudentId;}publicvoidstudy(){System.out.println(name 正在學(xué)習(xí));}}封裝帶來(lái)的好處數(shù)據(jù)更安全外部無(wú)法繞過(guò)校驗(yàn)直接修改修改內(nèi)部實(shí)現(xiàn)時(shí)不影響使用該類(lèi)的代碼代碼職責(zé)更清晰。4. 構(gòu)造方法簡(jiǎn)化對(duì)象初始化創(chuàng)建對(duì)象后還要一個(gè)個(gè)調(diào)用setter很麻煩我們可以引入構(gòu)造方法。構(gòu)造方法在創(chuàng)建對(duì)象時(shí)自動(dòng)調(diào)用用于完成初始化。publicclassStudent{privateStringname;privateStringstudentId;// 無(wú)參構(gòu)造方法publicStudent(){}// 帶參構(gòu)造方法publicStudent(Stringname,StringstudentId){this.namename;this.studentIdstudentId;}publicvoidstudy(){System.out.println(name 正在學(xué)習(xí));}}創(chuàng)建對(duì)象時(shí)就簡(jiǎn)潔多了StudentzhangsannewStudent(張三,2024001);zhangsan.study();構(gòu)造方法的特點(diǎn)方法名必須與類(lèi)名相同沒(méi)有返回值類(lèi)型如果不寫(xiě)構(gòu)造方法編譯器會(huì)提供一個(gè)默認(rèn)的無(wú)參構(gòu)造方法一旦寫(xiě)了任何構(gòu)造方法默認(rèn)的無(wú)參構(gòu)造方法就不再自動(dòng)提供。5. 完整的入門(mén)示例綜合以上內(nèi)容一個(gè)完整的Student類(lèi)如下publicclassStudent{privateStringname;privateStringstudentId;publicStudent(){}publicStudent(Stringname,StringstudentId){if(namenull||name.isEmpty()){thrownewIllegalArgumentException(姓名不能為空);}this.namename;this.studentIdstudentId;}publicStringgetName(){returnname;}publicStringgetStudentId(){returnstudentId;}publicvoidstudy(){System.out.println(namestudentId 正在學(xué)習(xí));}}測(cè)試代碼publicclassMain{publicstaticvoidmain(String[]args){StudentzhangsannewStudent(張三,2024001);StudentlisinewStudent(李四,2024002);zhangsan.study();lisi.study();}}這是一個(gè)典型的面向?qū)ο髮?xiě)法數(shù)據(jù)屬性被封裝在類(lèi)內(nèi)部通過(guò)構(gòu)造方法和行為對(duì)外提供有限的訪問(wèn)方式。6. 小結(jié)本篇我們掌握了三個(gè)核心內(nèi)容類(lèi)與對(duì)象類(lèi)是模板對(duì)象是實(shí)例封裝屬性私有化通過(guò)getter/setter訪問(wèn)保護(hù)數(shù)據(jù)安全構(gòu)造方法在創(chuàng)建對(duì)象時(shí)完成初始化。