剛接觸JAVA或者其他面向對象的思維以及類與對象
2021-06-08
對于剛接觸JAVA或其他面向對象編程語言的朋友來說,一開始可能很難理解面向對象的概念以及類與對象的關系。筆者曾經參加過一次短期培訓班,講授java基礎知識。在課程結束時,許多學生沒有理解面向對象的思想以及類和對象的含義。這幾天有空,想整理一下思路,談談我對面向對象和類和對象的理解。
面向對象
首先百度會得到如下定義:
一切都是對象。通過面向對象的方法,將現(xiàn)實世界中的事物抽象為對象,將現(xiàn)實世界中的關系抽象為類并繼承,幫助人們實現(xiàn)對現(xiàn)實世界的抽象化和數(shù)字化建模。
我們知道編寫程序的目的是解決現(xiàn)實生活中的問題,編程中的思維方式也應該接近現(xiàn)實生活中的思維方式。面向對象編程就是為了達到以上兩個目的。它使編程工作更加直觀和易于理解。需要注意的是,這里提到的編程不僅包括設計過程,還包括面向對象
為什么說面向對象更接近現(xiàn)實生活?
想象一下,當我們向別人描述某事時,我們都會說什么? “它的嘴像鴨子”,“它有四個退縮”,“它的爪子上有網”,“它是哺乳動物,但它是卵生的?!?/p>
HAS A 和 IS A 的這種表達方式往往可以簡單有效地描述同一事物。 HAS A描述事物的屬性或行為,IS A描述事物的類別。
當我們結合這一系列屬性時,我們得到鴨嘴獸的類別。同時,哺乳動物這個詞簡潔明了地表達了所有哺乳動物的特征,而不是一一列舉。這是繼承特性的體現(xiàn)。同時,卵子發(fā)育是多態(tài)性的一種表現(xiàn)。
這是面向對象思維的特點,它提取(抽象)有用的屬性和行為(丟棄那些不需要關系的)并組織(封裝)成一個類。在這個過程中,你可能會發(fā)現(xiàn)很多屬性或者方法和另一個類是一樣的,那么你可以使用繼承來避免重復(當然這個過程也可能是你設計了每個類之后,發(fā)現(xiàn)它們有共同點,然后提取基類)。更重要的是,繼承不能照原樣復制。我們可以通過重載來實現(xiàn)相同行為或屬性的唯一實現(xiàn)。此功能稱為多態(tài)性。比如同樣的生產行為,實現(xiàn)方式從胎生變?yōu)槁焉U埓舐暲首x并牢記面向對象的四個特點:
抽象、封裝、繼承、多態(tài),與早期結構化編程相比
早期結構化編程是面向過程的(功能)。換句話說,程序由一組函數(shù)組成數(shù)據結構用面向對象方法與c++描述,調用者作為函數(shù)的參數(shù)傳入。在面向對象的程序中,對象是主體,程序由對象的集合組成。一個對象包含一系列符合設計的函數(shù),供其他對象調用。所以它可能很抽象,
比如我們在設計五子棋游戲的時候,流程化的設計思路就是先分析問題:1、開始游戲,2、黑子先走,3、畫圖,4、判斷輸贏,5、轉白子,6、畫屏,7、判斷勝負,8、返回第2步,9、輸出最終結果。用單獨的函數(shù)分別執(zhí)行以上步驟,問題就解決了。
面向對象的設計是從另一種思維方式解決問題。整個五子棋可以分為:1、黑白,兩方的行為完全一樣,2、棋盤系統(tǒng),負責畫屏,3、rule系統(tǒng),負責判斷犯規(guī),獲勝或輸?shù)取5谝活悓ο螅ㄍ婕覍ο螅┴撠熃邮苡脩糨斎氩⑼ㄖ诙悓ο螅ㄆ灞P對象)棋子布局的變化。棋盤對象負責在接收到棋子的變化后在屏幕上顯示變化,同時使用前三種對象(規(guī)則系統(tǒng))來確定對局。 (以上例子來自國內某知名問答社區(qū))
隨便寫點代碼,看看就行,別太認真...
/** 玩家類 **/ 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 playerList=new ArrayList(); 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; } }
但是,其實通過上面的例子代碼,不難發(fā)現(xiàn),即使我們使用面向對象的方式,也已經實現(xiàn)了上面例子中提到的幾個象棋過程,只不過過程是封裝的進入類的方法。所以其實面向對象和面向過程不是編程的區(qū)別(需要實現(xiàn)的業(yè)務邏輯量不會變),而是設計的區(qū)別!
類和對象
類是抽象的,而對象是具體的
如何理解上面的單詞?例如,鴨嘴獸是一種類型,特定的鴨嘴獸 A 和鴨嘴獸 B 是對象。在 JAVA 中,對象是通過 new 關鍵字聲明的。再比如,《紅色警戒》中的美軍士兵是一種單位,點擊后從軍營中射出的那個就是目標:
類的定義是一個模板,它描述了一類對象的屬性和行為。類通常是抽象的,沒有實體。哺乳動物是屬的概念,是抽象的。實際上,沒有哺乳動物這樣的實體。只有具體的東西,比如老虎和獅子。在編程工作中應用這種思維方式,我們將程序中的實例抽象為類。例如,如果一個系統(tǒng)中的用戶有三、李四,我們將它們抽象為類,或者稱它們?yōu)槊麛?shù)據類型。
對象是基于它們所屬的類模板創(chuàng)建的真實事物。在程序中,我把這個有形的東西稱為實例。我們給它的屬性賦予特定的值,讓它成為張三或李斯。在內存中,對象代表特定的數(shù)據。
我上面說的都是概念性的東西,下面說說實際應用過程中的理解。
在數(shù)據類型方面
以java為例,數(shù)據類型分為基本數(shù)據類型和引用數(shù)據類型。
基本數(shù)據類型為byte,,,int,long,,char,;其他需要使用new關鍵字賦值的都是引用數(shù)據類型。類和對象指的是被引用數(shù)據的類型和值(這里指的類不僅包括接口、數(shù)組、枚舉和注解)。引用是指對內存地址的引用,后面講內存的時候會詳細討論這個。看下面的代碼:
int a =1; Person b=new Person();
a 和 b 都是無意義的變量名。需要注意的是:a的類型是基本數(shù)據類型int 為1,b的類型是引用類型,指的是對象new()。我們常說對象xx,比如這里的對象b。但實際上b只是一個對象的引用,真正的對象是new()!
需要注意的是,它也是一種引用數(shù)據類型,但是因為使用率非常高,所以可以像JVM的基本數(shù)據類型一樣使用:a = "abc";等同于 a = new ("abc") ;
簡而言之,簡單來說,類是指引用數(shù)據的類型,對象是具體的賦值。為了更深入的理解,我們需要在下面解釋這個引用是如何反映的。
什么是引用(來自記憶)
要深入理解什么是類,什么是對象,什么是引用,都離不開Java的內存使用。
在Java中,內存大致分為棧()和堆(heap)(之所以粗略是因為它還包括其他幾個部分,這里就不贅述了)。我不會在這里詳細說明什么是堆棧和堆。有時間我會整理一篇文章詳細講解。
這里只講一點:在Java中,基本的數(shù)據類型和對象引用是存放在棧()中,而對象是存放在堆(heap)中的,比如下面的代碼:
int a=1; Person p;
內存中的狀態(tài)大致如下:
int a = 1 直接在棧中開辟空間,沒有實例化的p的值為null,因為沒有有效的內存地址來引用它。而當代碼修改如下:
int a =1 ; Person p = new Person();
內存中的狀態(tài)大致如下:
p=new();使p的值=即對象的地址new();在堆中。所以不難理解前面提到的對象的引用,所謂引用其實就是對堆內存地址的引用。總結
隨著計算機技術的不斷進步,現(xiàn)在計算機不僅僅是用來解決計算問題,而是用來解決越來越接近現(xiàn)實生活的復雜問題。面向對象正是這一發(fā)展過程的產物,它使編程工作更貼近人們的思維方式,從而大大提高了編程效率。我們必須明白的是,面向對象不是一種編程方式,而是一種編程思維方式,包括分析、設計、編碼等。在面向對象編程中數(shù)據結構用面向對象方法與c++描述,程序的基本單元是對象,數(shù)據被封裝在對象中。類是一個對象模板,它是一個預定義的結構。所謂類的實例化,就是將數(shù)據填充到模板中。
最后,我的文筆不是很好,需要改進。寫文章和博客的最大目的是梳理自己的想法,其次是分享自己的想法。希望大家多多投訴,共同進步。