對(duì)于剛接觸JAVA或者其他面向?qū)ο缶幊陶Z言的朋友們來說低千,可能一開始都很難理解面向?qū)ο蟮母拍钜约?code>類和對(duì)象
的關(guān)系。筆者曾經(jīng)帶過一個(gè)短期培訓(xùn)班教授java入門基礎(chǔ)胧瓜,在最后結(jié)束課程的時(shí)候,還有很多同學(xué)不太理解面向?qū)ο?/code>的思維以及
類
與對(duì)象
的意義。這幾天有空帐要,就想著整理整理自己的思路,談?wù)勛约簩?duì)面向?qū)ο笠约邦惻c對(duì)象的理解烦却。
面向?qū)ο?/h1>
首先宠叼,一言不和先百度,得到如下定義:
一切事物皆對(duì)象,通過面向?qū)ο蟮姆绞矫岸瑢F(xiàn)實(shí)世界的事物抽象成對(duì)象伸蚯,現(xiàn)實(shí)世界中的關(guān)系抽象成類、繼承简烤,幫助人們實(shí)現(xiàn)對(duì)現(xiàn)實(shí)世界的抽象與數(shù)字建模剂邮。
我們知道,編寫程序的目的是為了解決現(xiàn)實(shí)生活中的問題横侦,編程的思維方式也應(yīng)該貼近現(xiàn)實(shí)生活的思維方式挥萌。面向?qū)ο蟮木幊谭绞骄褪菫榱藢?shí)現(xiàn)上述目的二出現(xiàn)的。它使得編程工作更直觀枉侧,更易理解引瀑。需要注意的是這里說的編程不光是coding還包括了設(shè)計(jì)的過程也是面向?qū)ο蟮?/strong>
為什么說面向?qū)ο蟾N近實(shí)際生活
想象一下,當(dāng)我們向別人描述一樣事物時(shí)榨馁,我們都是怎么說的憨栽?"它有像鴨子一樣的嘴巴","它有4條退"翼虫,"爪子里還有蹼"屑柔,"它是哺乳動(dòng)物但卻是卵生"。
這種HAS A
和 IS A
的表達(dá)方式往往可以簡(jiǎn)單而高效的描述一樣事物珍剑。HAS A
描述事物的屬性或行為掸宛,IS A
則說明了事物的類屬。
當(dāng)我們把這一系列的屬性組合
起來便得到的鴨嘴獸這一類
招拙,同時(shí)哺乳動(dòng)物
一詞簡(jiǎn)單精煉的表面了所有哺乳動(dòng)物的特性而不用一一列出唧瘾,這是繼承
特性的體現(xiàn),同時(shí)卵生
又是多態(tài)
的體現(xiàn)别凤。
這就是面向?qū)ο蟮乃季S特點(diǎn)劈愚,抽取(抽象
)有用的屬性和行為(拋棄哪些無需關(guān)系的)組織(封裝
)成一個(gè)類闻妓。這個(gè)過程中你也許會(huì)發(fā)現(xiàn)很多屬性或方法是和另一個(gè)類相同的菌羽,那么你就可以采用繼承
的方式避免重復(fù)(當(dāng)然這個(gè)過程也有可能是,當(dāng)你設(shè)計(jì)完一個(gè)個(gè)類后由缆,才發(fā)現(xiàn)他們有共同點(diǎn)注祖,然后再抽取出基類)。更重要的是均唉,繼承是可以不原樣照搬的是晨,我們可以通過重載
實(shí)現(xiàn)相同行為或?qū)傩缘奶赜袑?shí)現(xiàn)方式,這種特點(diǎn)稱之為多態(tài)
,例如同樣的生產(chǎn)行為舔箭,實(shí)現(xiàn)方式由胎生變?yōu)槁焉纸伞U?qǐng)大聲念出蚊逢,并牢牢記住面向?qū)ο蟮乃膫€(gè)特征:
- 抽象
- 封裝
- 繼承
- 多態(tài)
與早期結(jié)構(gòu)化編程相比
早期結(jié)構(gòu)化編程是面向過程的(功能),換句話說程序是由功能的集合組成箫章,而調(diào)用者是作為功能的參數(shù)傳入的烙荷。而在面向?qū)ο蟮某绦蛑校瑢?duì)象是主體檬寂,程序是由對(duì)象的集合組成终抽。一個(gè)對(duì)象中包含一系列符合設(shè)計(jì)的功能供其他對(duì)象調(diào)用。這么說可能還是比較抽象桶至,
昼伴,例如當(dāng)我們?cè)O(shè)計(jì)一個(gè)五子棋游戲時(shí),
面向過程的設(shè)計(jì)思路就是首先分析問題的步驟:
1镣屹、開始游戲圃郊,2、黑子先走女蜈,3描沟、繪制畫面,4鞭光、判斷輸贏,5泞遗、輪到白子惰许,6、繪制畫面史辙,7汹买、判斷輸贏,8聊倔、返回步驟2晦毙,9、輸出最后結(jié)果耙蔑。
把上面每個(gè)步驟用分別的函數(shù)來實(shí)現(xiàn)见妒,問題就解決了。
而面向?qū)ο蟮脑O(shè)計(jì)則是從另外的思路來解決問題甸陌。整個(gè)五子棋可以分為:
1须揣、黑白雙方,這兩方的行為是一模一樣的钱豁,2耻卡、棋盤系統(tǒng),負(fù)責(zé)繪制畫面牲尺,3卵酪、規(guī)則系統(tǒng),負(fù)責(zé)判定諸如犯規(guī)、輸贏等溃卡。
第一類對(duì)象(玩家對(duì)象)負(fù)責(zé)接受用戶輸入溢豆,并告知第二類對(duì)象(棋盤對(duì)象)棋子布局的變化,棋盤對(duì)象接收到了棋子的變化就要負(fù)責(zé)在屏幕上面顯示出這種變化塑煎,同時(shí)利用第三類對(duì)象(規(guī)則系統(tǒng))來對(duì)棋局進(jìn)行判定沫换。
(以上例子來自國(guó)內(nèi)著名問答社區(qū))
隨便寫點(diǎn)代碼,大家看看就好最铁,不要太認(rèn)真....
/**
玩家類
**/
public class Player {
String name; //棋手名稱
boolean isFirst; //是否先手
int color_flag; //代表顏色 0-白 1-黑
Table table;//棋盤對(duì)象
public Player(String name,boolean isFirst;int color_flag){
this.name=name;
this.isFirst=isFirst;
this.color_flag=color_flag;
}
/**
下棋讯赏,x,y為落子坐標(biāo)
**/
public void play(int x,int y) throws Exception{
if(this.table==null){
throw new IllegalArgumentException("玩家還未注冊(cè)到棋盤!");
}
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);
}
/**
注冊(cè)玩家
**/
public void registPlayer(Player player) throws Exception {
//檢測(cè)棋盤中的玩家是否已滿漱挎,先手玩家和玩家選色是否沖突。
.......
playerList.add(player);
player.setTable(this);
}
/**
落子
**/
public void setNewPieces(int x , int y){
//重新繪制棋盤
......
//調(diào)用裁判對(duì)象雀哨,判斷結(jié)果
if(referee.isEnd){
End();
}
}
public void End(){
.......
}
}
/**
裁判類
**/
public class Referee(){
Table table磕谅;
public Referee(Table table){
this.table=table;
}
public boolen isEnd(){
//判斷輸贏
....
return false;
}
}
然而事實(shí)上,通過上述示例代碼雾棺,我們不難發(fā)現(xiàn)膊夹,即使我們使用面向?qū)ο蟮姆绞剑厦胬永锩嫦蜻^程中提到的幾個(gè)下棋過程我們還是都實(shí)現(xiàn)了的捌浩,只不過程被封裝
到了類的方法中放刨。所以說其實(shí)面向?qū)ο蠛兔嫦蜻^程并不是編程的區(qū)別(需要實(shí)現(xiàn)的業(yè)務(wù)邏輯的量不會(huì)產(chǎn)生變化),而是設(shè)計(jì)的區(qū)別尸饺!
類與對(duì)象
類是抽象的,而對(duì)象是具體的
如何理解上面的話呢进统? 例如鴨嘴獸是類型,具體的鴨嘴獸A浪听、鴨嘴獸B就是對(duì)象了螟碎。在JAVA中對(duì)象是通過new
關(guān)鍵字聲明的。 再例如迹栓,《紅色警戒》中美國(guó)大兵是一類
兵種掉分,點(diǎn)擊制造后從兵營(yíng)里出來的那個(gè)會(huì)開槍的家伙就是對(duì)象
了:
類
的定義就是一個(gè)模板,它描述的一類對(duì)象的屬性與行為克伊。類往往是抽象的叉抡、沒有實(shí)體的。哺乳動(dòng)物是類
的概念答毫,是抽象的褥民,現(xiàn)實(shí)中沒有哺乳動(dòng)物這一實(shí)體,只有具體的如老虎洗搂,獅子等消返。編程工作中套用這一思維模式载弄,我們將程序中的實(shí)例抽象為類,例如一個(gè)系統(tǒng)中的用戶有張三撵颊、李四我們會(huì)把他們抽象為Person類宇攻,或者稱之為一個(gè)名為Person的數(shù)據(jù)類型。
對(duì)象
則是根據(jù)所屬類
模板創(chuàng)造出來的實(shí)實(shí)在在的事物倡勇。在程序中我將這個(gè)實(shí)實(shí)在在的事物稱之為實(shí)例逞刷,我們?yōu)樗膶傩再x上特定的值,讓它成為張三或者李四妻熊。在內(nèi)存里來說夸浅,對(duì)象是表示的就是具體數(shù)據(jù)。
前面說的都是概念性的東西扔役,下面我們說說實(shí)際的運(yùn)用過程中的理解帆喇。
從數(shù)據(jù)類型來說
以java為例,數(shù)據(jù)類型分為基本數(shù)據(jù)類型
和引用數(shù)據(jù)類型
亿胸。
基本數(shù)據(jù)類型就是byte,short,int,long,double,char,boolean
坯钦;其它的,需要用到new
關(guān)鍵字來賦值的都是引用數(shù)據(jù)類型侈玄。 類與對(duì)象指的便是引用數(shù)據(jù)的類型與其值(這里指的類不光是class
婉刀,還包括接口、數(shù)組序仙、枚舉突颊、注解
)。 而引用指的是內(nèi)存地址的引用诱桂,關(guān)于這點(diǎn)在后面說的內(nèi)存時(shí)會(huì)細(xì)說。
看下面的代碼:
int a =1;
Person b=new Person();
a 和 b 都是本身無意義的變量名呈昔。需要關(guān)注的是:a的類型是基本數(shù)據(jù)類型int值為1挥等,而b的類型是Person屬于引用類型,其引用的是new Person()這個(gè)對(duì)象堤尾。我們往往會(huì)說對(duì)象xx肝劲,比如這里的對(duì)象b。但實(shí)際上b只是對(duì)象的引用郭宝,真正的對(duì)象是后面的new Person()辞槐!
需要注意的是String也是引用數(shù)據(jù)類型,只不過因?yàn)槭褂寐史浅8哒呈遥詫?duì)于String榄檬,jvm支持其可 以像基本數(shù)據(jù)類型一樣使用:String a = "abc"; 同等于 String a = new String("abc");
總之呢,簡(jiǎn)單來說類
指的的引用數(shù)據(jù)的類型衔统,對(duì)象
是具體賦的值鹿榜。為了更深入理解海雪,我們下面需要解釋下這個(gè)引用
是如何體現(xiàn)的。
什么是引用(從內(nèi)存來說)
要深入理解什么是類舱殿,什么是對(duì)象奥裸,什么又是引用,就離不開說說java的內(nèi)存使用方式沪袭。
在java中內(nèi)存被大致劃分為棧(stack)
與堆(heap)
(之所以是大致湾宙,是因?yàn)檫€包括其它幾部分就不在這細(xì)說)。
關(guān)于什么是棧與堆在這就不細(xì)說冈绊,有空我再整理一篇文章詳細(xì)說明侠鳄。
在這里我們只說一點(diǎn):java中,基本數(shù)據(jù)類型以及對(duì)象的引用都保存在棧(stack)
焚碌,而對(duì)象則保存在堆(heap)
中畦攘,例如當(dāng)如下代碼:
int a=1;
Person p;
內(nèi)存中的狀態(tài)大致如下:
int a = 1 是直接在棧中開辟空間,而對(duì)于未進(jìn)行實(shí)例化的Person p因?yàn)闆]有有效的內(nèi)存地址引用它的值是null十电。而當(dāng)代碼進(jìn)行如下修改時(shí):
int a =1 ;
Person p = new Person();
內(nèi)存中的狀態(tài)大致如下:
Person p=new Person();
使得p的值=0x8da23也就是對(duì)象new Person()知押;
在堆
中的地址。所以鹃骂,到這里后就不難理解之前說的對(duì)象的引用了台盯,所謂引用其實(shí)就是堆內(nèi)存地址的引用。
總結(jié)
隨著計(jì)算機(jī)技術(shù)的不斷提高畏线,現(xiàn)在計(jì)算機(jī)不單單是用來解決運(yùn)算問題静盅,而是被用于解決越來越貼近現(xiàn)實(shí)生活的復(fù)雜問題。面向?qū)ο缶褪沁@一發(fā)展進(jìn)程的產(chǎn)物寝殴,它使得編程工作更貼近人的思維方式蒿叠,從而大大提升編程效率。我們必須明白的是面向?qū)ο蟛⒉皇且环N編程方式蚣常,而是一種編程思維方式市咽,這種思維方式涵蓋了分析,設(shè)計(jì)抵蚊,編碼等施绎。在面向?qū)ο缶幊讨校绦虻幕締卧?code>對(duì)象贞绳,數(shù)據(jù)封裝在對(duì)象中谷醉。類
是對(duì)象模板,是預(yù)定義好的結(jié)構(gòu)冈闭,所謂的實(shí)例化一個(gè)類俱尼,所指的就是將數(shù)據(jù)填入模板。
最后萎攒,本人文筆不是很好号显,有待提高臭猜。寫文章和博客的最大目的是梳理自己的思路,其二是分享自己的想法押蚤,望大家多多吐槽蔑歌,愿共同提高。