文章最初發表於個人我的博客非典型性程序猿java
對於剛接觸JAVA或者其餘面向對象編程語言的朋友們來講,可能一開始都很難理解面向對象的概念以及類
和對象
的關係。筆者曾經帶過一個短時間培訓班教授java入門基礎,在最後結束課程的時候,還有不少同窗不太理解面向對象
的思惟以及類
與對象
的意義。這幾天有空,就想着整理整理本身的思路,談談本身對面向對象以及類與對象的理解。編程
首先,一言不和先百度,獲得以下定義:數組
一切事物皆對象,經過面向對象的方式,將現實世界的事物抽象成對象,現實世界中的關係抽象成類、繼承,幫助人們實現對現實世界的抽象與數字建模。jvm
咱們知道,編寫程序的目的是爲了解決現實生活中的問題,編程的思惟方式也應該貼近現實生活的思惟方式。面向對象的編程方式就是爲了實現上述目的二出現的。它使得編程工做更直觀,更易理解。須要注意的是這裏說的編程不光是coding還包括了設計的過程也是面向對象的編程語言
想象一下,當咱們向別人描述同樣事物時,咱們都是怎麼說的?"它有像鴨子同樣的嘴巴","它有4條退","爪子裏還有蹼","它是哺乳動物但倒是卵生"。函數
這種HAS A
和 IS A
的表達方式每每能夠簡單而高效的描述同樣事物。HAS A
描述事物的屬性或行爲,IS A
則說明了事物的類屬。佈局
當咱們把這一系列的屬性組合
起來便獲得的鴨嘴獸這一類
,同時哺乳動物
一詞簡單精煉的表面了全部哺乳動物的特性而不用一一列出,這是繼承
特性的體現,同時卵生
又是多態
的體現。this
這就是面向對象的思惟特色,抽取(抽象
)有用的屬性和行爲(拋棄哪些無需關係的)組織(封裝
)成一個類。這個過程當中你也許會發現不少屬性或方法是和另外一個類相同的,那麼你就能夠採用繼承
的方式避免重複(固然這個過程也有多是,當你設計完一個個類後,才發現他們有共同點,而後再抽取出基類)。更重要的是,繼承是能夠不原樣照搬的,咱們能夠經過重載
實現相同行爲或屬性的特有實現方式,這種特色稱之爲多態
,例如一樣的生產行爲,實現方式由胎生變爲卵生。請大聲念出,並緊緊記住面向對象的四個特徵:編碼
抽象spa
封裝
繼承
多態
早期結構化編程是面向過程的(功能),換句話說程序是由功能的集合組成,而調用者是做爲功能的參數傳入的。而在面向對象的程序中,對象是主體,程序是由對象的集合組成。一個對象中包含一系列符合設計的功能供其餘對象調用。這麼說可能仍是比較抽象,
,例如當咱們設計一個五子棋遊戲時,
面向過程的設計思路就是首先分析問題的步驟:
一、開始遊戲,二、黑子先走,三、繪製畫面,四、判斷輸贏,五、輪到白子,六、繪製畫面,七、判斷輸贏,八、返回步驟2,九、輸出最後結果。
把上面每一個步驟用分別的函數來實現,問題就解決了。
而面向對象的設計則是從另外的思路來解決問題。整個五子棋能夠分爲:
一、黑白雙方,這兩方的行爲是如出一轍的,二、棋盤系統,負責繪製畫面,三、規則系統,負責斷定諸如犯規、輸贏等。
第一類對象(玩家對象)負責接受用戶輸入,並告知第二類對象(棋盤對象)棋子佈局的變化,棋盤對象接收到了棋子的變化就要負責在屏幕上面顯示出這種變化,同時利用第三類對象(規則系統)來對棋局進行斷定。
(以上例子來自國內著名問答社區)
隨便寫點代碼,你們看看就好,不要太認真....
/** 玩家類 **/ public class Player { String name; //棋手名稱 boolean isFirst; //是否先手 int color_flag; //表明顏色 0-白 1-黑 Table table;//棋盤對象 public Player(String name,boolean isFirst;int color_flag){ this.name=name; this.isFirst=isFirst; this.color_flag=color_flag; } /** 下棋,x,y爲落子座標 **/ public void play(int x,int y) throws Exception{ if(this.table==null){ throw new IllegalArgumentException("玩家還未註冊到棋盤!"); } table.setNewPieces(x,y); } public void setTable(Table table){ this.table=table; } } /** 棋盤類 **/ public class Table{ List<Player> playerList=new ArrayList<Player>(); Referee referee ; public Table(){ referee =new Referee(this); } /** 註冊玩家 **/ public void registPlayer(Player player) throws Exception { //檢測棋盤中的玩家是否已滿,先手玩家和玩家選色是否衝突。 ....... playerList.add(player); player.setTable(this); } /** 落子 **/ public void setNewPieces(int x , int y){ //從新繪製棋盤 ...... //調用裁判對象,判斷結果 if(referee.isEnd){ End(); } } public void End(){ ....... } } /** 裁判類 **/ public class Referee(){ Table table; public Referee(Table table){ this.table=table; } public boolen isEnd(){ //判斷輸贏 .... return false; } }
然而事實上,經過上述示例代碼,咱們不難發現,即便咱們使用面向對象的方式,上面例子裏面向過程當中提到的幾個下棋過程咱們仍是都實現了的,只不過程被封裝
到了類的方法中。因此說其實面向對象和麪向過程並非編程的區別(須要實現的業務邏輯的量不會產生變化),而是設計的區別!
類是抽象的,而對象是具體的
如何理解上面的話呢? 例如鴨嘴獸是類型,具體的鴨嘴獸A、鴨嘴獸B就是對象了。在JAVA中對象是經過new
關鍵字聲明的。 再例如,《紅色警惕》中美國大兵是一類
兵種,點擊製造後從兵營裏出來的那個會開槍的傢伙就是對象
了:
類
的定義就是一個模板,它描述的一類對象的屬性與行爲。類每每是抽象的、沒有實體的。哺乳動物是類
的概念,是抽象的,現實中沒有哺乳動物這一實體,只有具體的如老虎,獅子等。編程工做中套用這一思惟模式,咱們將程序中的實例抽象爲類,例如一個系統中的用戶有張3、李四咱們會把他們抽象爲Person類,或者稱之爲一個名爲Person的數據類型。
對象
則是根據所屬類
模板創造出來的實實在在的事物。在程序中我將這個實實在在的事物稱之爲實例,咱們爲它的屬性賦上特定的值,讓它成爲張三或者李四。在內存裏來講,對象是表示的就是具體數據。
前面說的都是概念性的東西,下面咱們說說實際的運用過程當中的理解。
以java爲例,數據類型分爲基本數據類型
和引用數據類型
。
基本數據類型就是byte,short,int,long,double,char,boolean
;其它的,須要用到new
關鍵字來賦值的都是引用數據類型。 類與對象指的即是引用數據的類型與其值(這裏指的類不光是class
,還包括接口、數組、枚舉、註解
)。 而引用指的是內存地址的引用,關於這點在後面說的內存時會細說。
看下面的代碼:
int a =1; Person b=new Person();
a 和 b 都是自己無心義的變量名。須要關注的是:a的類型是基本數據類型int值爲1,而b的類型是Person屬於引用類型,其引用的是new Person()這個對象。咱們每每會說對象xx,好比這裏的對象b。但實際上b只是對象的引用,真正的對象是後面的new Person()!
須要注意的是String也是引用數據類型,只不過由於使用率很是高,因此對於String,jvm支持其可 以像基本數據類型同樣使用:String a = "abc"; 同等於 String a = new String("abc");
總之呢,簡單來講類
指的的引用數據的類型,對象
是具體賦的值。爲了更深刻理解,咱們下面須要解釋下這個引用
是如何體現的。
要深刻理解什麼是類,什麼是對象,什麼又是引用,就離不開說說java的內存使用方式。
在java中內存被大體劃分爲棧(stack)
與堆(heap)
(之因此是大體,是由於還包括其它幾部分就不在這細說)。
關於什麼是棧與堆在這就不細說,有空我再整理一篇文章詳細說明。
在這裏咱們只說一點:java中,基本數據類型以及對象的引用都保存在棧(stack)
,而對象則保存在堆(heap)
中,例如當以下代碼:
int a=1; Person p;
內存中的狀態大體以下:
int a = 1 是直接在棧中開闢空間,而對於未進行實例化的Person p由於沒有有效的內存地址引用它的值是null。而當代碼進行以下修改時:
int a =1 ; Person p = new Person();
內存中的狀態大體以下:Person p=new Person();
使得p的值=0x8da23也就是對象new Person();
在堆
中的地址。因此,到這裏後就不難理解以前說的對象的引用了,所謂引用其實就是堆內存地址的引用。
隨着計算機技術的不斷提升,如今計算機不僅僅是用來解決運算問題,而是被用於解決愈來愈貼近現實生活的複雜問題。面向對象就是這一發展進程的產物,它使得編程工做更貼近人的思惟方式,從而大大提高編程效率。咱們必須明白的是面向對象並非一種編程方式,而是一種編程思惟方式,這種思惟方式涵蓋了分析,設計,編碼等。在面向對象編程中,程序的基本單元是對象
,數據封裝在對象中。類
是對象模板,是預約義好的結構,所謂的實例化一個類,所指的就是將數據填入模板。
最後,本人文筆不是很好,有待提升。寫文章和博客的最大目的是梳理本身的思路,其二是分享本身的想法,望你們多多吐槽,願共同提升。