從崛起的智人到被蘋果砸中的牛頓再到如今的你,一直在思考「這是個怎麼樣的世界?」
看到一張蘋果的圖片,腦海裏天然浮現「圖片上的是一個蘋果」,爲何會稱蘋果爲‘蘋果’?java
世界上全部的物質都是客觀存在的,基於事物固有的特性,人類用本身方式將其抽象爲具體的概念並用一些媒介表達了出來,這些媒體如語言、繪畫、手語等。
將客觀存在事物抽象爲咱們本身的概念,便能方便平常的交流和對事物的研究利用。對事物進行抽象定義的質量越高,咱們使用起來越方便。在平常生活中,當說起到這些事物時咱們對這些事物的特徵、功能也老是‘心中有數’。編程
咱們解決問題的能力直接取決於咱們對事物抽象的質量。工具
計算機也是咱們表達和使用抽象的一種有效媒介。設計
進行程序設計的目的就是解決實際生活中一些的問題,程序老是和實際息息相關的。將實際問題中元素用計算機的方式來進行抽象定義,而後利用這些抽象來解決問題。這樣咱們直面的便問題空間中的抽象,在解決問題是基於問題的結構,而不是基於計算機結構。code
不使用面向對象時,可能寫出下面的代碼(僞代碼):對象
/*將一個用戶信息保存到文件*/ userName = "xxxx"; userAge = "18"; userTel = "11111"; fileName = "xxxxxx"; // 保存信息到文件 file = open(fileName); file.write(userName); file.write(userAge); file.write(userTel); file.close();
這樣的代碼用戶相關信息在碼層面並無提現出強烈的相關,他們都只是一個個獨立的變量。只有咱們本身知道他們是‘一塊兒’的,並實時維護他的關係。在保存信息到文件時,總時要打開、寫入、關閉,對於不少個信息就繁瑣且複雜。繼承
使用面向對象來解決這個問題,先將用戶信息抽象出來並將抽象的定義的類放到一個單獨的文件中:圖片
class UserInfo { name; age; tel; FILE_NAME = "xxxxxx"; function saveUserInfo() { file = open(FILE_NAME); file.write(userName); file.write(userAge); file.write(userTel); file.close(); } }
這裏,用戶的各個信息一目瞭然的他們是‘一塊兒’的,而且將寫的操做也進行了抽象封裝。在解決問題的代碼文件中使用定義好的抽象:it
userUnfo = new UserInfo(); userInfo.name = "xxx"; userInfo.age = 18; userInfo.tel = "11111"; userinfo.saveUserInfo();
這一部分代碼纔是咱們真正須要的用來解決問題的代碼。這裏咱們沒必要時刻當心的維護用戶信息各個部分是'一塊兒'的,在這他們都屬於UserInfo的屬性,保存文件時也沒必要再考慮其實現的細節,這些細節咱們已經作好了封裝,在這裏只須要使用就行。io
利用計算機來對事物進行抽象並使用即是面向對象編程。
將水燒開,咱們須要熱水器和電。將水倒入插電的熱水器,打開開關將水燒開。在這個過程當中咱們並不關心熱水器的具體實現,也不關心電是這產生的等等,這些全部的東西都是「封裝」好的,咱們只使用好這些東西就行。
編程來解決這個問題時,何不妨一樣先將熱水器等的屬性和功能進行封裝。而後在使用這些封裝好的元素來解決問題,就如同實際中同樣天然流暢。而不是在每一個步驟都調用計算機相關的特性來實現,這樣會讓整個問題和計算機的實現混合不清。
類與對象:
面向對象中用類來描述事物的屬性和功能,對事物進行抽象即是抽象爲一個類。
對象是類的一個具體實例。如某天看到的一隻鳥,這隻鳥即是鳥類的一個具體實例。
經過定義類將問題空間中元素的進行了封裝,而後實例化類的對象來爲問題的求解提供服務。
類也是自定義的數據類型:
一個類定義完成後即是一個咱們本身定義的數據類型。像建立內置類型的變量同樣建立類的變量(即類的對象),而後操做這些對象。每一個對象都有其類的特性,而每個對象有是獨立的一個變量。
生活中使用程序提供的服務來解決問題,而程序的又調用各個對象提供的服務來來實現。這些對象和實際問題中的各個元素同樣,經過調用這些元素完成特定的功能來解決問題。對象的調用即是調用對象的方法,每個方法知足了特定的需求。
在面向對象中一切都是對象,每一個對象提供服務或數據給其餘對象,對象之間互相調用和傳遞數據來解決問題
一個新類和原有類具備類似的功能,只是添加了部分新功能或部分功能不同,咱們又得從新定義重複的功能,這樣顯得很麻煩,代碼不具有複用性。 這類需求在面向對象中使用繼承來處理。
經過繼承新的類便具有了原有類的功能和特性的同時又能夠進行本身的擴展建立出一個新類。被繼承的類稱爲基類,繼承基類的新類稱爲導出類。一般將一些共性和核心建立爲基類,再經過繼承來建立新不一樣實現的新類。
繼承時,導出類繼承了基類全部的特性和功能,這也就意味着全部對基類的調用,在導出類中一樣也具備並能夠調用,如此意味着導出類與基類是同一的類型。但基類與導出類卻不是同一類型,由於對導出類添加的新特性基類並不具有。
因此能夠將導出類的實例對象賦給基類,做爲一個基類對象使用。但這時是並不能夠訪問導出類的新方法,畢竟導出類同基類是同一類型,但基類同導出類不是同一類型,由於導出類會添加或修改類功能。
你有不少部手機,但每一部手機的充電器都是不同的,當其中一部手機須要充電的時,你對助理說「幫我衝下電」,助理天然會去找合適充電器,沒必要告訴助理手機是什麼型號去找什麼樣的充電器。
將這些手機進行封裝
先將手機共有的特性封裝爲一個Phone基類,基類包括充電這個共性功能。而後繼承這個類並覆蓋基類的充電方法,來實現每一類型的充電的具體實現。
生活中咱們說手機充電,這裏手機是一個大的類型,但咱們知道該用那個一個充電器。
既然在繼承時導出類和基類是同一個類型,那麼當咱們把一個派生類對象賦給基類時,對於那些覆蓋了基類的功能,一樣也應該知道在須要時去調用派生類的實現。
Phone p = new Apple(); p.charge();
經過繼承新加了Apple手機的類,而後建立Apple類並將它賦值給了Phone類型,那麼當調用充電時天然應該去調用Apple本身的充電方法。
根據對象具體實現取去查找其對應的方法,這就是多態。
固然多態對於產生覆蓋的方法纔有意義,畢竟雖然導出類和基類能夠視爲統一類型是由於導出類繼承了基類的所有,但基類卻並不擁有導出類的新特性。因此在一個基類對象上調用導出類的新功能者並無什麼意義,也不符合現實。畢竟在生活中咱們能夠說交通工具載貨,但並不會說交通工具起飛,而是說飛機起飛。但對於導出類覆蓋基類的方法,導出類和基類都有這樣功能,只是實現不一樣,因此多態在此時顯得有意義且必要。
產生差別:在導出類中添加新的特性或覆蓋