談談我對面向對象以及類與對象的理解

文章最初發表於個人我的博客非典型性程序猿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();中的地址。因此,到這裏後就不難理解以前說的對象的引用了,所謂引用其實就是堆內存地址的引用。

總結

隨着計算機技術的不斷提升,如今計算機不僅僅是用來解決運算問題,而是被用於解決愈來愈貼近現實生活的複雜問題。面向對象就是這一發展進程的產物,它使得編程工做更貼近人的思惟方式,從而大大提高編程效率。咱們必須明白的是面向對象並非一種編程方式,而是一種編程思惟方式,這種思惟方式涵蓋了分析,設計,編碼等。在面向對象編程中,程序的基本單元是對象,數據封裝在對象中。是對象模板,是預約義好的結構,所謂的實例化一個類,所指的就是將數據填入模板。

最後,本人文筆不是很好,有待提升。寫文章和博客的最大目的是梳理本身的思路,其二是分享本身的想法,望你們多多吐槽,願共同提升。

相關文章
相關標籤/搜索