您好,登錄后才能下訂單哦!
這篇文章主要介紹“編程語言中面向對象的介紹以及使用方法”,在日常操作中,相信很多人在編程語言中面向對象的介紹以及使用方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”編程語言中面向對象的介紹以及使用方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
什么是面向對象
面向對象(Object Oriented)是軟件開發方法。面向對象的概念和應用已超越了程序設計和軟件開發,擴展到如數據庫系統、交互式界面、應用結構、應用平臺、分布式系統、網絡管理結構、CAD技術、人工智能等領域。面向對象是一種對現實世界理解和抽象的方法,是計算機編程技術發展到一定階段后的產物。 面向對象是相對于面向過程來講的,面向對象方法,把相關的數據和方法組織為一個整體來看待,從更高的層次來進行系統建模,更貼近事物的自然運行模式。 百度百科
依據以上解釋,初學者很難理解什么是面向對象,大概做個簡單解釋,因為面向對象的概念非常大,所以大家有什么意見或建議請與我聯系。
面向對象是一個方法論,采用這種方法論,軟件開發人員能夠更好的進行開發工作;
面向對象是區別于面向過程的一個方法論,關于面向過程請看第2點;
Object的中文含義是“目標”、“物體”等,面向對象,即站在一個Object的角度去思考;
面向對象的語言都是高級語言,主流有Java\C++\Python\Objective-C\JavaScript\Python\PHP等(排名不分先后);
在面向對象中,現實世界的一個事物即為一個對象,各自有其不同屬性(形狀\顏色等),不同行為(功能)。使用編程語言把這些屬性和行為描述成一個抽象的對象,且不同的編程語言有不同的表達方式。
面向過程
“面向過程”(Procedure Oriented)是一種以過程為中心的編程思想。這些都是以什么正在發生為主要目標進行編程,不同于面向對象的是誰在受影響。與面向對象明顯的不同就是封裝、繼承、類。百度百科
??有人說,女朋友/男朋友就是對象。顯然,這個說法是正確的。因為,每個人都有一些屬性,比如:姓名、性別、身高、年齡、身份證號等等;也有一些行為,例如:走路、吃飯、工作等。
??萬事萬物都是一個對象,人們描述一個事物,經常通過一些名稱、形狀和很多特征去描述,比如 是人、直立行走、會使用工具等,那么這個過程,是自然語言描述一個事物的過程,在面向對象編程中,同樣可以使用相似的語言描述成一個事物,那么這個事物代表人,以JavaScript代碼為例:
??女朋友是被丈母娘生下來的,那么編程中的對象,也是被創建出來的,以上方法就是在JavaScript中創建一個對象的過程。
面向對象程序設計(Object Oriented Programming)作為一種新方法,其本質是以建立模型體現出來的抽象思維過程和面向對象的方法。模型是用來反映現實世界中事物特征的。任何一個模型都不可能反映客觀事物的一切具體特征,只能對事物特征和變化規律的一種抽象,且在它所涉及的范圍內更普遍、更集中、更深刻地描述客體的特征。通過建立模型而達到的抽象是人們對客體認識的深化。百度百科
??通俗來講,我們把現實世界的一個事物,使用編程語言描述成編程世界中的對象,然后再去使用這些對象進行對更高一級世界的構建的過程,就是面向對象編程。
??我們描述出什么是學生,什么是老師,什么是課程,可以構成一個課程管理系統;同樣,我們描述出商品,描述出用戶,描述出訂單,可以構成一個網上商城。
封裝
把一個對象的屬性和行為,封裝到一個不可分割的獨立實體,把自己可以被外界訪問的通過受保護的接口公開,即屬性私有,方法公開。
??上面的內容太官方,封裝,用一臺電腦比喻,包含主板、CPU、內存條、硬盤、顯卡等等,這些是不可被人直接去操作的。那么我們同樣能夠通過鍵盤、鼠標、顯示器等輸入輸出設備去訪問操作這臺電腦。
??我們無法直接去訪問其被包起來的內容,這些屬于電腦私有的,是不可以被訪問的,當然我們可以通過輸入輸出設備去操作這臺電腦,這部分是對外開放的,你可以進行訪問的。
??聽起來就像是電腦的外殼把它的核心組件給封裝了起來,然后通過一些插口來接入鍵盤鼠標,你進行操作。沒錯,這就是封裝。
class Computer{ String cpu; int memory; String gpu; String hardDisk public void powerOn(){ //開機 } public void powerOff(){ //關機 } }
繼承
子類繼承父類,可以使得子類具有父類的方法和屬性,無需重寫父類的方法即可調用。子類同樣可以重寫父類的方法使得父類的方法具有不同的的功能。子類可以追加新的方法,使得子類的功能更豐富。
??雖然不是兒子繼承父親遺產,但是同樣,兒子可以擁有父親的資產。子類繼承了父類,擁有父類的方法和屬性。
??在編程中的繼承,是因為抽象的原因導致的,比如,英語老師和數學老師,物理老師,都可以繼承 "老師" 這個父類,而老師,是在這個過程中屬于一個抽象的概念,那么三位老師都有教學的這個功能,同樣都有職業證書、職稱等等屬性。這個特性也會造成下一個面向對象的特性——多態。
??但是不一樣的是,物理老師可以修電表,英語老師可以和外國人交流,數學老師同樣能用數學方法解決生活中的問題。顯然他們都是老師的情況下,每個老師也有自己的超能力。
class Teacher{ String title;//職稱 String subject;//所授課程 void teach(){ //教學 } } class EnglishTeacher extends Teacher{ private String englishLevel;//英語等級 void teach(){ System.out.println("I am teaching English") } void talkToForeigners(){ //和外國人對話 } }
多態
不同對象對同一個操作可以做出不同的反應,產生不同的執行結果。可以通過指向基類的指針,來調用實現派生類中的方法。
??老師都可以教學,那么不同的老師,所教的內容不一樣,數學老師教我們數學,英語老師教我們英語,而物理老師教我們物理。
??此處我們當然是需要調用父類(老師)的教學方法,但是因為不同的子類重寫了父類的方法,所以當通過調用父類的方法的時候,才會產生不同的結果。
??向上造型是產生多態的基石,比如我們可以這么寫 Teacher teacher = new MathTeacher() 來實現向上造型,此時我們調用 teacher.teach() 方法,則會調用到數學老師的 teach() 方法。
關于抽象
抽象是指從具體事物抽出、概括出它們共同的方面、本質屬性與關系等,而將個別的、非本質的方面、屬性與關系舍棄的思維過程。
??抽象并沒有被列到面向對象三大特征中,相對來說,個人認為這個是面向對象的基本方法,所有面向對象的特征都基于,先進行抽象,才能構建出對象。
??我們在編程過程中會盡可能的使用抽象思維,將一個或者一類現實世界的事物,使用面向對象語言,變成編程中的對象。
?? 比如剛才我們把三個不同的老師抽象成老師,事實上我們還可以把老師歸并到學校的工作人員,把學校工作人員歸并為社會工作人員,更可以把社會工作人員歸并為人類。當然,越是抽象的對象,其屬性和方法就會更少,以為共同點更少了。
開閉原則
開閉原則規定“軟件中的對象(類,模塊,函數等等)應該對于擴展是開放的,但是對于修改是封閉的”,這意味著一個實體是允許在不改變它的源代碼的前提下變更它的行為。該特性在產品化的環境中是特別有價值的,在這種環境中,改變源代碼需要代碼審查,單元測試以及諸如此類的用以確保產品使用質量的過程。百度百科-開閉原則
應該對于擴展是開放的,但是對于修改是封閉的
這句話不好理解,但是可以看一個例子:
/** * <p> mapper基類 </p> * * @author Calvin * @date 2019/11/07 * @since */ public abstract class BaseMapper<BaseEntity>{ /** * 新增或保存 * @param entity */ public void saveOrUpdate(BaseEntity entity){ String id = entity.getId(); BaseEntity exists = null; if(StringUtils.isNotEmpty(id) && (exists = this.findById(id)) == null){ this.save(entity); }else{ this.update(entity); } } /** * 根據ID查找,抽象方法 * @param id * @return */ abstract BaseEntity findById(String id); /** * 新增 * @param entity */ abstract void save(BaseEntity entity); /** * 修改 * @param entity */ abstract void update(BaseEntity entity); }
通過定義一個baseMapper,以后有新增的Mapper中有saveOrUpdate方法,我們只需要令其實現BaseMapper, 使得 其對應的Bean去繼承 BaseEntity,這樣我們就能夠橫向進行擴展。
class UserMapper extends BaseMappper{ @Override public User findById(String id){ // select * from user where id = #{id} } @Override public void save(User user){ // insert into user ...... } @Override public void update(User user){ //update user set .... where id = #{user.id} } }
另外有三點約束:
第一,通過接口或者抽象類約束擴展,對擴展進行邊界限定,不允許出現在接口或抽象類中不存在的public方法;
第二,參數類型、引用對象盡量使用接口或者抽象類,而不是實現類;
第三,抽象層盡量保持穩定,一旦確定即不允許修改。
找到一篇帖子,個人認為是融會貫通了:https://www.liangzl.com/get-article-detail-133084.html
接口隔離
客戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。百度百科-接口隔離原則
也就是說,如果一個類,實現了一個擁有三個方法的接口,而這個類本身只需要使用其中兩個,那么,此時違背了接口隔離的原則。
interface Interface1 { void function1(); void function2(); void function3(); }
class A implements Interface1{ @Override public void function1(){ //被需要的 } @Override public void function2(){ //被需要的 } @Override public void function3(){ //不被需要的 } }
此時需要對接口進行改造,一般意義上是根據功能或者其領域,拆分成不同的接口。
interface Interface1 { void function1(); void function2(); }
interface Interface2 { void function3(); }
拆分成兩個接口后,A類只實現Interface1,不需要實現Interface2,就可以了,代碼略,此時就算是簡單遵循了接口隔離。
接口隔離要注意的點:
接口要高內聚。什么是高內聚?高內聚就是提高接口、類、模塊的處理能力,減少對外的交互,就比如一個人,你告訴下屬“到奧巴馬的辦公室偷一個XX文件”,然后就聽到下屬就堅定的口吻回答你“好的,保證完成!”,然后一個月后還真的把XX文件放到你的辦公桌了,這種不講任何條件、立刻完成任務的行為就是高內聚的表現。具體到接口隔離原則就是要求在接口中盡量少公布public方法,接口是對外的承諾,承諾越少對系統的開發越有利,變更的風險也就越少,同時也有利于降低成本。
定制服務。一個系統或系統內的模塊之間必然會有耦合,有耦合就要相互訪問的接口(并不一定就是Java中定義的Interface,也可能是一個類或者是單純的數據交換),我們設計時就需要給各個訪問者(也就是客戶端)定制服務,什么是定制服務?單獨為一個個體提供優良優良的服務。我們在做系統設計時也需要考慮對系統之間或模塊之間的定義要采用定制服務,采用定制服務就必然有一個要求就是:只提供訪問者需要的方法,只暴露給調用的類它需要的方法,它不需要的方法則隱藏起來。只有專注地為一個模塊提供定制服務,才能建立最小的依賴關系。
接口盡量小,但是要有限度。接口的設計粒度是越小系統越靈活,這是不爭的事實,但是這就帶來成接口數量過多,使設計結構的復雜化,開發難度增加,維護性降低,這不是一個項目或產品所期望看到的。所以一定要適度。
本部分轉載自:https://blog.csdn.net/u012361379/article/details/88101102
職責單一
它規定一個類應該只有一個發生變化的原因。百度百科-單一職責原則
此處的一個類只能有一個發生變化的原因
此處是指,由于業務場景等原因導致的變化,而不是代碼運行期間的變化。解釋略有一點含糊,導致筆者在很早之前對此不是特別懂。
class UserMapper{ User findOne(String id){ //TODO } User insertOne(User user){ //TODO } void updateById(User user){ //TODO } User generateUser(String username, String password){ User user = new User(); user.setId(UUID.generateUUID().toString()); user.setUsername(username); user.setPassword(password); insertOne(user) } }
以上是一個反例,這個類當中存在一個生成學生的方法,還有插入新增查詢的方法,生成學生的方法依賴于新增。
此時無論是生成學生的方法發生變化,還是插入學生的方法發生變化,都可能導致另一個方法(以至于這個類)發生變化。
代碼進行修改
class UserMapper{ User findOne(String id){ //TODO } User insertOne(User user){ //TODO } void updateById(User user){ //TODO } } class UserGenerator{ UserMapper userMapper; UserGenerator(UserMapper userMapper){ this.userMapper = userMapper; } User generateUser(String username, String password){ User user = new User(); user.setId(UUID.generateUUID().toString()); user.setUsername(username); user.setPassword(password); userMapper.insertOne(user) } }
里式替換
任何基類可以出現的地方,子類一定可以出現。 百度百科-里式替換原則
??里氏代換原則是很多其它設計模式的基礎。它和開放封閉原則的聯系尤其緊密。違背了里氏代換原則就一定不符合開放封閉原則。還是Teacher那個代碼:
public TeacherTest{ public static void main(String [] args){ Teacher teacher = new MathTeacher(); teacher.teach(); MathTeacher mathTeacher = new MathTeacher(); mathTeacher.teach(); } }
??兩個測試方法執行結果會完全一樣。
一:子類可以實現父類的抽象方法,但是不能覆蓋父類的非抽象方法.【核心觀念】
二:子類中可以增加自己特有的方法.
三:前置條件放大,子類在重載父類的已實現方法時,方法的前置條件(形參)范圍應該比父類更加寬松.
四:后置條件縮小,子類在實現父類的抽象方法時,方法的后置條件(返回值)范圍應該比父類更加嚴格或相同.
??此部分原文鏈接:https://blog.csdn.net/hongxiancheng/article/details/83049746
依賴倒置
程序要依賴于抽象接口,不要依賴于具體實現。高層次的模塊不應該依賴低層次的模塊,二者應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。簡單的說就是要求對抽象進行編程,不要對實現進行編程,這樣就降低了客戶與實現模塊間的耦合。
有認識過SpringMVC的人一定懂這個:
public interface UserService{ User create(HashMap args); }
@Mapper public interface UserMapper{ void insert(User user); }
public class UserServiceImpl implements UserService{ @Autowride private UserMapper userMapper; public User create(HashMap args){ User user = UserParser.fromMap(args); userMapper.insert(user); } }
這就是典型的依賴倒置,調用方不用關心UserMapper具體實現是什么,只需依賴此接口,就能完成自己的業務邏輯。
依賴倒置原則假定所有的具體類都是會變化的;
為避免對類的直接調用,依賴倒置可能會使得項目產生更多的類;
面向接口編程
會使你更好的利用依賴倒置原則;
?
6. 迪特米法則
迪米特法則(Law of Demeter)又叫作最少知識原則(Least Knowledge Principle 簡寫LKP),就是說一個對象應當對其他對象有盡可能少的了解,不和陌生人說話。百度百科-迪特米法則
一個女孩子
public class Girl{ private BoyFriend boyFriend; public void getBoyFriend(){ return this.boyFriend(); } }
女孩的男朋友
public class BoyFriend{ public void receiveMessage(String message){ //response } }
女孩的閨蜜
public class BosomFriend{ private Girl girl; BosomFriend(Girl girl){ this.girl = girl; } public void talk(){ String message = "I am so cold!"; BoyFriend boyFriend = girl.getBoyFriend(); boyFriend.receiveMessage(message); } }
此時,你的閨蜜直接告訴你男朋友的她很冷,顯然違背了迪特米法則,那么你應該怎么做,以后他們的任何通信必須通過你。
public class Girl{ private BoyFriend boyFriend; public void getBoyFriend(){ return this.boyFriend(); } //把你跟你男朋友說話的方法暴露出來 public void talkToBoyFriend(String message){ if(StringUtils.isNotEmpty(message)){ //過濾一下說的什么內容 boyFriend.receiveMessage(message); }else{ //當然不能告訴男朋友了 } } }
以后他們交流就可以通過你交流,這樣避免他們私下里溝通。當閨蜜類不再依賴男朋友類的時候,就遵從了迪特米原則。
public class BosomFriend{ private Girl girl; BosomFriend(Girl girl){ this.girl = girl; } public void talk(){ String message = "I am so cold!"; girl.talkToBoyFriend(message); } }
盡量減少對象之間的交互,從而減小類之間的耦合。簡言之,一定要做到:低耦合,高內聚。
在做系統設計時,不要讓一個類依賴于太多的其他類,需盡量減小依賴關系。
1、本文簡單介紹了面向對象和其核心概念;
2、簡單通過代碼,演示了面向對象的特征;
3、通過demo詳細介紹了面向對象的SOLID五大原則和迪特米法則;
到此,關于“編程語言中面向對象的介紹以及使用方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。