談談我對物件導向以及類與物件的理解
來源:http://justin-x.cn/
對於剛接觸JAVA或者其他物件導向程式語言的朋友們來說,可能一開始都很難理解物件導向的概念以及類
和物件
的關係。筆者曾經帶過一個短期培訓班教授java入門基礎,在最後結束課程的時候,還有很多同學不太理解物件導向
的思維以及類
與物件
的意義。這幾天有空,就想著整理整理自己的思路,談談自己對物件導向以及類與物件的理解。
物件導向
首先,一言不和先百度,得到如下定義:
一切事物皆物件,通過物件導向的方式,將現實世界的事物抽象成物件,現實世界中的關係抽象成類、繼承,幫助人們實現對現實世界的抽象與數字建模。
我們知道,編寫程式的目的是為了解決現實生活中的問題,程式設計的思維方式也應該貼近現實生活的思維方式。物件導向的程式設計方式就是為了實現上述目的二出現的。它使得程式設計工作更直觀,更易理解。需要注意的是這裡說的程式設計不光是coding還包括了設計的過程也是物件導向的。
為什麼說物件導向更貼近實際生活
想象一下,當我們向別人描述一樣事物時,我們都是怎麼說的?”它有像鴨子一樣的嘴巴”,”它有4條退”,”爪子裡還有蹼”,”它是哺乳動物但卻是卵生”。
這種HAS A
和 IS A
的表達方式往往可以簡單而高效的描述一樣事物。HAS A
描述事物的屬性或行為,IS A
則說明了事物的類屬。
當我們把這一系列的屬性組合
起來便得到的鴨嘴獸這一類
,同時哺乳動物
一詞簡單精煉的表面了所有哺乳動物的特性而不用一一列出,這是繼承
特性的體現,同時卵生
又是多型
的體現。
這就是物件導向的思維特點,抽取(抽象
)有用的屬性和行為(拋棄哪些無需關係的)組織(封裝
)成一個類。這個過程中你也許會發現很多屬性或方法是和另一個類相同的,那麼你就可以採用繼承
的方式避免重複(當然這個過程也有可能是,當你設計完一個個類後,才發現他們有共同點,然後再抽取出基類)。更重要的是,繼承是可以不原樣照搬的,我們可以通過過載
實現相同行為或屬性的特有實現方式,這種特點稱之為多型
,例如同樣的生產行為,實現方式由胎生變為卵生。請大聲念出,並牢牢記住物件導向的四個特徵:
抽象
封裝
繼承
多型
與早期結構化程式設計相比
早期結構化程式設計是程式導向的(功能),換句話說程式是由功能的集合組成,而呼叫者是作為功能的引數傳入的。而在物件導向的程式中,物件是主體,程式是由物件的集合組成。一個物件中包含一系列符合設計的功能供其他物件呼叫。這麼說可能還是比較抽象~
例如:當我們設計一個五子棋遊戲時
程式導向的設計思路就是首先分析問題的步驟:
1、開始遊戲,2、黑子先走,3、繪製畫面,4、判斷輸贏,5、輪到白子,6、繪製畫面,7、判斷輸贏,8、返回步驟2,9、輸出最後結果。
把上面每個步驟用分別的函式來實現,問題就解決了。
而物件導向的設計則是從另外的思路來解決問題。
整個五子棋可以分為:
1、黑白雙方,這兩方的行為是一模一樣的,2、棋盤系統,負責繪製畫面,3、規則系統,負責判定諸如犯規、輸贏等。
第一類物件(玩家物件)負責接受使用者輸入,並告知第二類物件(棋盤物件)棋子佈局的變化,棋盤物件接收到了棋子的變化就要負責在螢幕上面顯示出這種變化,同時利用第三類物件(規則系統)來對棋局進行判定。(以上例子來自國內著名問答社群)
隨便寫點程式碼,大家看看就好,不要太認真…
/**
玩家類
**/
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
關鍵字宣告的。 再例如,《紅色警戒》中美國大兵是一類
兵種,點選製造後從兵營裡出來的那個會開槍的傢伙就是物件
了:
類
的定義就是一個模板,它描述的一類物件的屬性與行為。類往往是抽象的、沒有實體的。哺乳動物是類
的概念,是抽象的,現實中沒有哺乳動物這一實體,只有具體的如老虎,獅子等。程式設計工作中套用這一思維模式,我們將程式中的例項抽象為類,例如一個系統中的使用者有張三、李四我們會把他們抽象為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();
在堆
中的地址。所以,到這裡後就不難理解之前說的物件的引用了,所謂引用其實就是堆記憶體地址的引用。
總結
隨著計算機技術的不斷提高,現在計算機不單單是用來解決運算問題,而是被用於解決越來越貼近現實生活的複雜問題。物件導向就是這一發展程式的產物,它使得程式設計工作更貼近人的思維方式,從而大大提升程式設計效率。
我們必須明白的是物件導向並不是一種程式設計方式,而是一種程式設計思維方式,這種思維方式涵蓋了分析,設計,編碼等。在物件導向程式設計中,程式的基本單元是物件
,資料封裝在物件中。類
是物件模板,是預定義好的結構,所謂的例項化一個類,所指的就是將資料填入模板。
最後,本人文筆不是很好,有待提高。寫文章和部落格的最大目的是梳理自己的思路,其二是分享自己的想法,望大家多多吐槽,願共同提高。
PS:如果覺得我的分享不錯,歡迎大家隨手點贊、轉發。
(完)
Java團長
專注於Java乾貨分享
掃描上方二維碼獲取更多Java乾貨
相關文章
- 面試——談談你對Java 物件導向思想的理解面試Java物件
- 淺談JS物件導向JS物件
- Java物件導向——類與物件Java物件
- python物件導向思想(類與物件)Python物件
- 再和“物件導向”談戀愛 - 物件簡介物件
- 10 Python物件導向程式設計:類和物件以及和Java的對比Python物件程式設計Java
- JS的物件導向(理解物件,原型,原型鏈,繼承,類)JS物件原型繼承
- 說下你對物件導向的理解物件
- 淺談PHP物件導向程式設計PHP物件程式設計
- Js物件導向(1): 理解物件JS物件
- Java語言之物件導向—類與物件(上)Java物件
- 請用物件導向的思想,談一談面試的過程物件面試
- python中物件導向_類_物件的概念與定義Python物件
- 從 Java 到 Scala(一):物件導向談起Java物件
- 如何理解“物件導向”物件
- 是時候談談JavaScript物件導向了!(我們什麼時候更需要它)JavaScript物件
- 淺談物件導向中的一些主要思想物件
- 課時37:類與物件:物件導向程式設計物件程式設計
- 談談我對Spring IOC的理解Spring
- 《JavaScript物件導向精要》之三:理解物件JavaScript物件
- 物件導向與程式導向物件
- 程式導向與物件導向物件
- JavaScript 物件導向初步理解JavaScript物件
- 如何理解物件導向(一)物件
- 物件導向 -- 類的組合物件
- 物件導向-物件導向思想物件
- python-程式導向、物件導向、類Python物件
- 深入理解python物件導向-類特殊成員Python物件
- JAVA物件導向--抽象類Java物件抽象
- 物件導向的基本理論1:類和物件物件
- 談談我對服務化的理解
- 談一談我對Spring Resource的理解Spring
- 我對JavaScript物件的理解JavaScript物件
- TypeScript與物件導向TypeScript物件
- Golang 物件導向深入理解Golang物件
- php中的程式導向與物件導向PHP物件
- 談談JavaScript 的Navigator 物件JavaScript物件
- 與面試官談笑風生 | Python物件導向之訪問控制面試Python物件