面向對象是什么?你可以說出這個答案嗎(相信沒有正確答案)?我覺得面向對象只是軟件工程中的一種工具而已。那軟件工程的目的是什么?目的是編寫出可靠、高效、靈活、易擴展、可復用的軟件產品。既然面向對象是軟件工程當中的一種工具,那我們使用面向對象的目的也應該是這些。就是說我們用面向對象的目的是編寫出可靠、高效、靈活、易擴展、可復用的軟件產品。我們一定要以這個目的為中心來學習和使用面向對象,不然你會失去方向。大多時候講面向對象,多是講面向對象本身,而不講怎么利用面向對象去解決實際的問題,這樣很容易誤導初學者。再加上華麗的文字,很多人覺得只要面向對象了,什么事都可以OK了。舉個例子,給你一把最好的槍,教你如何使用它,過了一段時間你對這把槍了如指掌。現在讓你去打靶,結果100發子彈,一發都沒有打中。咦,我不是用了最好的槍了嗎?為什么一發都打不中?因為你不知道射擊要領,不知道如何瞄準靶心,結果當然可想而知了。我們要OOP(Object-Oriented Programming),不要POO(Programming Object-Oriented)。
面向對象有3大特征(一般講面向對象都會提到這三個),繼承、封裝、多態。按字面上理解,對我們來說是全新的概念,但只要你分析一下,就會發現這些都是我們在編程中,常常用到的概念。
封裝是什么?只有在面向對象里才有封裝的概念嗎?不是的,只要是程序就有封裝。大家常常用的變量、函數就是封裝。舉個例子,你寫了取用戶狀態的函數,對調用這個函數的程序來說,取用戶狀態邏輯是封閉的,所以邏輯發生變化時,不會對調用的程序造成影響。變量也是封裝,你定義了一個int變量,無論你給它賦什么值,對調用這個變量的程序來說,就是一個整數型類型的值。提到封裝不得不提接口,因為封裝是做接口的過程。接口是什么?只有用了interface這個關鍵字才是接口嗎?詞典里的解釋是物體的接觸面、界面。世界是由物體組成的,所以我們的生活當中到處是接口。你看到一個球,它是圓的,圓就是接口。我們的程序也都是由接口組成的,數據類型、關鍵字、函數、變量等等。比如說看到int這個詞,你就知道它是整數型數據類型,我們可以說:int是整數型數據類型的接口。所以封裝和接口不是面向對象特有的概念,只不過在面向對象里它們的范圍擴大了而已。我們在網上常常能看到面向對象和面向過程之間的討論,說哪一個好。其實,這些都是不重要的,因為用哪一個方法,都是做接口的過程。關鍵在于使用這些方法的程序員,看你的抽象能力怎么樣了。
多態可能是我們最難理解的一個概念,polymorphism這個詞,因為大家沒有學習過面向對象的話,是很難碰到的。其實這個也是我們常常用到的一個概念,只不過沒有給它命名而已(至少沒用多態來命名它)。看下面的例子, double a = 0,b=5,c=0;
a = 1;
c = a + b;
cout << c << endl;
a = 3.5f;
c = a + b;
cout << c endl;
輸出結果是
6
8.5
我們先定義了三個變量,a、b、c,先后給A賦值1,3.5,然后輸出a+b的結果,可以看到,同樣的邏輯隨著a值的變化,輸出的結果也是不一樣的(多態的效果)。在這里double是高類型(相當于父類),1、3.5(int,float)是低類型(相當于子類)。這個例子是變量的多態,那有沒有函數多態的例子,當然有,寫過C的人都知道函數指針,它就是函數的多態。
終于要說說對象了,重點就在這里~ 第一,類是一個模塊。以前我們的模塊是一個文件,比如一個.c、.cpp等等。一個模塊文件里寫什么功能函數沒有限制(理論上沒有明確定義該怎么寫),按開發人員的經驗來部署這些功能函數。所以很容易寫出超級模塊(一個文件里有幾十個、幾百個函數),代碼維護起來很不方便。面向對象就很好的解決了這個問題,只要看過面向對象基礎理論的程序員都知道,先定義類,然后把相關的函數放到類里。面向對象里有一個原則,類單一職責原則,遵循這個原則的話,你可以寫出很好的模塊出來。更重要的是我們溝通維護起來也很方便,比如以前溝通可能是這樣的,修改customer.cpp文件里的某一個函數,面向對象里呢,可以這樣說修改客戶類的某一個方法。這個非常重要,因為這個跟人的思維有密切關系。比如我們到餐廳去吃飯,你對服務員說我要一瓶啤酒,我確信服務員會再問你一句:先生,你要什么牌子的啤酒?但如果你說:我要一瓶百威啤酒,服務員肯定不會再問你。要是把一個系統看成生產線的話,類就是工人。一個工人只負責一個操作,A負責打孔,B負責裝螺絲釘,C負責包裝。這樣做非常有效率,而且出了問題,很好確定問題出現在哪個工人。第二,類是一個自定義數據類型。理解了這點,你的思路會清晰起來,也不會對面向對象感到陌生。看下面的簡單例子,
//計算兩個數的合
double sum(double a,double b);
int _tmain(int argc, _TCHAR* argv[])
{
double a=0,b=0;
a = 1;
b = 2;
cout << sum(a,b) << endl;
a = 1.2f;
b = 2.3f;
cout << sum(a,b) << endl;
return 0;
}
//計算兩個數的合
double sum(double a,double b)
{
return a+b;
}
例子里,低類型的int和float賦值給了高類型的double,然后用sum函數它們的合。如果編程語言不支持這種轉換的話,我們只好寫兩個函數了,
//處理int的計算
int sum(int a,int b);
//處理float的計算
float sum(float a,float b);
所以我們可以確定-同類型當中,只有提供從低到高類型的轉換,才可以實現多態的效果(不知道,沒有面向對象以前是什么概念)。當然,類作為數據類型,也需要這種轉換了。但類是自定義類型,所以,哪個是高類型,哪個是低類型,必須要由我們來定義:父類是高類型、子類是低類型(繼承是這么誕生的嗎:))。繼承讓我們可以復用父類的代碼,但在這個例子中我們可以看出,它的主要目的是在多態。
上面我們討論了面向對象和它的三個特征,我們可以看到,這些都是編程當中常常用到的概念。我覺得最大的突破是給我們提供了新的思維模式、新的代碼組織結構、定義了以前軟件設計中比較模糊的概念(比如多態)。那我們怎么轉換我們的思維呢?把你想象成公司的經理就可以了。你現在是一家公司的經理了,部門就是子系統,員工就是對象。你需要做的就是這些,
-每天會有很多事需要你處理,做好心里準備。
-公司做什么業務?
-要建立幾個部門?,規定部門之間的溝通規則。
-需要什么樣的職位?每個職位要做的事是什么?
-規定業務流程,業務流程中,需要哪個部門參與?需要哪個員工參與?他們之間怎么溝通?
-借鑒成功的管理模式,但要符合公司的情況,不要盲目地使用,因為代價太大了。
-不要設置太多的溝通環節,能簡單就簡單,只要完成目標就可以。
-準備應對變化。世界上沒有對于錯,永遠是前進中不斷修正。
就這些啦?恩,道理很簡單,但要做一個好公司就非常困難了,因為變數太大了。面向對象也是一樣的,需要付出努力,才可以做好。