本文原創作者:pipi-changing本文原創出處:http://www.cnblogs.com/pipi-changing/ 本文版權歸作者和博客園共有,未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接 ,否則保留追究法律責任的權利。 面向對象概念 理解面向對象 面向對象是相對面向 ...
本文原創作者:pipi-changing
面向對象概念
理解面向對象 面向對象是相對面向過程而言 面向對象和麵向過程都是一種思想 面向過程 •強調的是功能行為 面向對象 •將功能封裝進對象,強調具備了功能的對象。 面向對象是基於面向過程的。 面向過程
在一個結構體中定義視窗的大小,位置,顏色,背景等屬性,對視窗操作的函數與視窗本身的定義沒有任何關係, 如HideWindow,MoveWindow,MinimizeWindow,這些函數都需要接受一個代表要被操作的視窗參數 , 是一種謂語與賓語的關係 。
面向對象
定義視窗時,除了要指定在面向過程中規定的那些屬性,如大小,位置,顏色,背景等外,還要指定該視窗可能具有的動作 , 如隱藏,移動,最小化等。這些函數被調用時,都是以某個視窗要隱藏,某個視窗要移動的語法格式來使用的 , 這是一種主語與謂語的關係。
面向過程的思想和麵向對象的思想面向對象和麵向過程的思想有著本質上的區別, 作為面向對象的思維來說,當你拿到一個問題時, 你分析這個問題不再是第一步先做什麼, 第二步再做什麼,這是面向過程的思維,你應該分析這個問題裡面有哪些類和對象,這是第一點, 然後再分析這些類和對象應該具有哪些屬性和 方法。這是第二點。最後分析類和類之間具體有什麼關係,這是第三點。 面向對象有一個非常重要的設計思維:合適的方法應該出現在合適的類裡面
面向對象的設計思想 面向對象的基本思想是,從現實世界中客觀存在的事物出發來構造軟體系統,併在系統的構造中儘可能運用人類的自然思維方式。 面向對象更加強調運用人類在日常生活的邏輯思維中經常採用的思想方法與原則,如抽象、分類,繼承、聚合、多態等。 人在思考的時候,首先眼睛里看到的是一個一個的對象。
面向對象的特點 是一種符合人們思考習慣的思想 可以將複雜的事情簡單化 將程式員從執行者轉換成了指揮者 完成需求時: • 先要去找具有所需的功能的對象來用。 • 如果該對象不存在,那麼創建一個具有所需功能的對象。 • 這樣簡化開發並提高復用。
面向對象開發,設計,特征 開發的過程:其實就是不斷的創建對象,使用對象,指揮對象做事情。 設計的過程:其實就是在管理和維護對象之間的關係。 面向對象的特征: •封裝(encapsulation) •繼承(inheritance) •多態(polymorphism)
面向對象還支持如下幾個功能: 1)對象是面向對象方法中最基本的概念,它的基本特點是:標識唯一性、分類性、多態性、封裝性、模塊獨立性好。 2)類是具有共同屬性、共同方法的一類事物。類是對象的抽象;對象則是類的實例。 而類是整個軟體系統最小的程式單元,類的封裝性將各種信息細節隱藏起來,並通過公用方法來暴露該類對所提供的功能, 從而提高了類的內聚性,降低了對象之間的耦合性。 3)對象間的這種相互合作需要一個機制協助進行,這樣的機制稱為“消息”。消息是一個實例與另一個實例之間相互通信的機制。 4)在面向對象方法中,類之間共用屬性和操作的機制稱為繼承。繼承具有傳遞性。 繼承可分為單繼承(一個繼承只允許有一個直接父類,即類等級為樹形結構)與多繼承(一個類允許有多個直接父類), 但Java不支持多繼承。
在Java語言中除了8個基本數據類型值之外,一切都是對象,而對象就是面向對象程式設計的中心。 對象具有狀態,一個對象用數據值來描述它的狀態。Java通過對對象定義Field(以前常被稱為屬性,現在也稱欄位)來描述對象的狀態; 對象還有操作,這些操作可以改變對象的狀態, 對象的操作也被稱為對象的行為,Java通過為對象定義方法來描述對象的行為。 對象是Java程式的核心,所以在Java里的對象具有唯一性,每個對象都有一個標識來引用它, 如果某個對象失去了標識,這個對象將變成垃圾,只能等著系統垃圾回收機制來回收它。Java語言不允許直接訪問對象, 而是通過對對象的引用來操作對象。
在Java語言使用class關鍵字定義類,定義類時可使用Field來描述該類對象的數據,可使用方法來描述該類對象的行為特征。 Java語言使用extends關鍵字來表示繼承關係。
Java使用new關鍵字來創建指定類的對象,每個類可以創建任意多個對象,多個對象的Field值可以不同。 類與對象的關係 使用電腦語言就是不斷的在描述現實生活中的事物。 java中描述事物通過類的形式體現,類是具體事物的抽象,概念上的定義。 對象即是該類事物實實在在存在的個體。 類是對某一類事物的描述,是抽象的、概念上的定義;對象是實際存在的該類事物的每個個體,因而也稱實例(instance)。 類與對象的關係如圖
可以理解為: •類就是圖紙 •汽車就是堆記憶體中的對象
對於同一類事物可以抽取它們的共性的內容,定義在類中。 如生活中的汽車,每一臺車都有輪胎數和顏色。 那麼在通過java描述汽車這類事物時,就可以將這兩個共性屬性作為類中的屬性進行定義。 通過該類建立的每一個汽車實體都具有該屬性,並可以有對象特有的屬性值。
類的定義 生活中描述事物無非就是描述事物的屬性和行為。 •如:人有身高,體重等屬性,有說話,打球等行為。 Java中用類class來描述事物也是如此 •屬性:對應類中的成員變數。 •行為:對應類中的成員函數。 定義類其實在定義類中的成員(成員變數和成員函數)。 每一個JAVA裡面的class(類)都對應了我們現實生活中某一類事物的一個抽象。
成員變數和局部變數的區別? 成員變數: •成員變數定義在類中,在整個類中都可以被訪問。 •成員變數隨著對象的建立而建立,存在於對象所在的堆記憶體中。 •成員變數有預設初始化值。 局部變數: •局部變數只定義在局部範圍內,如:函數內,語句內等。 •局部變數存在於棧記憶體中。 •作用的範圍結束,變數空間會自動釋放。 •局部變數沒有預設初始化值。 方法體中局部變數若與成員變數同名,局部變數將屏蔽成員變數。 class Variable {
int x = 0, y = 0, z = 0; // 類的成員變數
void init(int x, int y) {
this.x = x;
this.y = y;
int z = 5; // 局部變數
System.out.println("** in init**");
System.out.println("x = " + x + "y = " + y + "z = " + z);
}
}
public class VariableTest {
public static void main(String args[]) {
Variable v = new Variable();
System.out.println("** before init **");
System.out.println("x = " + v.x + "y = " + v.y + "z = " + v.z);
v.init(20, 30);
System.out.println("** after init **");
System.out.println("x = " + v.x + "y = " + v.y + "z = " + v.z);
}
}
創建對象,使用對象 class Car//對Car這類事物進行描述
{
String color = "red";
int num = 4;
void show()
{
System.out.println("color="+color+"..num="+num);
}
}
1 class CarDemo
2 {
3 public static void main(String[] args)
4 {
5 Car c = new Car();//建立對象
6 c.color = "black";//對對象的屬性進行修改
7 c.show();//使用對象的功能。
8 }
9 }
對象記憶體結構
Car c1 = new Car(); c1.color="blue";
Car c2 = new Car();
只要是用new操作符定義的實體就在會堆記憶體中開闢一個新的空間。 並每一個對象中都有一份屬於自己的屬性。 通過 對象.對象成員 的方式操作對象中的成員, 對其中一個對象的成員進行了修改。和另一個對象沒有關係。
匿名對象 匿名對象是對象的簡化形式 匿名對象兩種使用情況 •當對對象方法僅進行一次調用時 •匿名對象可以作為實際參數進行傳遞
封裝(Encapsulation)
封裝:是指隱藏對象的屬性和實現細節,僅對外提供公共訪問方式。 好處: •將變化隔離。 •便於使用。 •提高重用性。 •提高安全性。 封裝原則: •將不需要對外提供的內容都隱藏起來。 •把屬性都隱藏,提供公共方法對其訪問。
封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始於這個基本概念, 即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的介面訪問其他對象。封裝隱藏了類的內部實現機制, 從而可以在不影響使用者的前提下改變類的內部結構,同時保護了數據。
private(私有)關鍵字
private關鍵字:
•是一個許可權修飾符。
•用於修飾成員(成員變數和成員函數)
•被私有化的成員只在本類中有效。
常用之一:
•將成員變數私有化,對外提供對應的set ,get方法對其進行訪問。提高對數據訪問的安全性。
構造函數
特點: 1.函數名與類名相同 2.不用定義返回值類型 3.沒有具體的返回值。作用: 給對象進行初始化。 註意: 1.預設構造函數的特點。 2.多個構造函數是以重載的形式存在的。
this關鍵字
特點:this代表其所在函數所屬對象的引用。 換言之:this代本類對象的引用。
什麼時候使用this關鍵字呢? 當在函數內需要用到調用該函數的對象時,就用this。
static(靜態)關鍵字
static關鍵字: •用於修飾成員(成員變數和成員函數) 被修飾後的成員具備以下特點: 隨著類的載入而載入 優先於對象存在 被所有對象所共用 可以直接被類名調用 使用註意 靜態方法只能訪問靜態成員 靜態方法中不可以寫this,super關鍵字 主函數是靜態的
繼承的概述
多個類中存在相同屬性和行為時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行為,只要繼那個類即可。 多個類可以稱為子類,單獨這個類稱為父類或者超類。 子類可以直接訪問父類中的非私有的屬性和行為。 通過 extends 關鍵字讓類與類之間產生繼承關係。 •class SubDemo extends Demo{} 繼承的出現提高了代碼的復用性。 繼承的出現讓類與類之間產生了關係,提供了多態的前提。
註意:子類不可以具備父類中私有的內容。 父類怎麼來的?共性不斷向上抽取而來的。
繼承關係封裝了這樣一種邏輯:“XX是一種XX”,只要能說通,就可以考慮用繼承關係來封裝它。
繼承的特點
Java只支持單繼承,不支持多繼承。 •一個類只能有一個父類,不可以有多個父類。 •class SubDemo extends Demo{} //ok •class SubDemo extends Demo1,Demo2...//error Java支持多層繼承(繼承體系) •class A{} •class B extends A{} •class C extends B{} 定義繼承需要註意: •不要僅為了獲取其他類中某個功能而去繼承 •類與類之間要有所屬( " is a " )關係,xx1是xx2的一種。
註意:因為多繼承容易出現問題。 兩個父類中有相同的方法。子類到底要執行哪一個是不確定的。 所以java不支持多繼承,但將這種機制換了另一個種安全的方式來體現,多實現。 多次繼承出現的繼承體系中,通常看父類中的功能,瞭解該體系的基本功能,建立子類對象即可使用該體系功能。
繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。 對象的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類), 而原始類稱為新類的基類(父類)。 派生類可以從它的基類那裡 繼承方法和實例變數,並且類可以修改或增加新的方法使之更適合特殊的需要。 因此可以說,繼承是為了重用父類代碼,同時為實現多態性作准備。
super關鍵字
super和this的用法相像 this代表本類對象的引用 super代表父類的記憶體空間的標識。 當子父類出現同名成員時,可以用super進行區分 子類要調用父類構造函數時,可以使用super語句。
函數覆蓋(Override)
子類中出現與父類一模一樣的方法時,會出現覆蓋操作,也稱為重寫或者覆寫。 父類中的私有方法不可以被覆蓋。 在子類覆蓋方法中,繼續使用被覆蓋的方法可以通過super.函數名獲取。 覆蓋註意事項: •覆蓋時,子類方法許可權一定要大於等於父類方法許可權 •靜態只能覆蓋靜態。 覆蓋的應用: •當子類需要父類的功能,而功能主體子類有自己特有內容時,可以覆寫父類中的方法, 這樣,即沿襲了父類的功能,又定義了子類特有的內容。
子類的實例化過程
子類中所有的構造函數預設都會訪問父類中空參數的構造函數 因為每一個構造函數的第一行都有一條預設的語句super(); 子類會具備父類中的數據,所以要先明確父類是如何對這些數據初始化的。 當父類中沒有空參數的構造函數時,子類的構造函數必須通過this或者super語句指定要訪問的構造函數。
final關鍵字
final可以修飾類,方法,變數。 final修飾的類不可以被繼承。 final修飾的方法不可以被覆蓋。 final修飾的變數是一個常量。只能被賦值一次。 內部類只能訪問被final修飾的局部變數。
抽象類概述 抽象定義: •抽象就是從多個事物中將共性的,本質的內容抽取出來。 •例如:狼和狗共性都是犬科,犬科就是抽象出來的概念。 抽象類: •Java中可以定義沒有方法體的方法,該方法的具體實現由子類完成,該方法稱為抽象方法,包含抽象方法的類就是抽象類。 抽象方法的由來: •多個對象都具備相同的功能,但是功能具體內容有所不同,那麼在抽取過程中,只抽取了功能定義,並未抽取功能主體, 那麼只有功能聲明,沒有功能主體的方法稱為抽象方法。 •例如:狼和狗都有吼叫的方法,可是吼叫內容是不一樣的。所以抽象出來的犬科雖然有吼叫功能,但是並不明確吼叫的細節。 抽象——就是忽略一個主題中與當前目標無關的那些方面,以便更充分地註意與當前目標有關的方面。 (就是把現實世界中的某一類東西,提取出來,用程式代碼表示,抽象出來一般叫做類或者介面。)抽象並不打算瞭解全部問題,
而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是數據抽象,二是過程抽象。
數據抽象——就是用代碼的形式表示現時世界中一類事物的特性,就是針對對象的屬性。 比如建立一個鳥這樣的類,鳥都有以下屬性:一對翅膀、兩隻腳、羽毛等。抽象出來的類都是鳥的屬性,或者成員變數。
過程抽象——就是用代碼形式表示現實世界中事物的一系列行為,就是針對對象的行為特征(方法)。 比如鳥會飛、會叫等。抽象出來的類一般都是鳥的方法。
抽象類的特點
抽象類和抽象方法必須用abstract關鍵字來修飾。 抽象方法只有方法聲明,沒有方法體,定義在抽象類中。 •格式:修飾符 abstract 返回值類型 函數名(參數列表) ; 抽象類不可以被實例化,也就是不可以用new創建對象。原因如下: •抽象類是具體事物抽取出來的,本身是不具體的,沒有對應的實例。例如:犬科是一個抽象的概念,真正存在的是狼和狗。 •而且抽象類即使創建了對象,調用抽象方法也沒有意義。 抽象類通過其子類實例化,而子類需要覆蓋掉抽象類中所有的抽象方法後才可以創建對象,否則該子類也是抽象類。
用abstract關鍵字修飾類:抽象類
用abstract關鍵字修飾方法:抽象方法
抽象類必須被繼承,抽象方法必須被重寫
抽象方法只需聲明,無需實現
抽象類不能被實例化,抽象類不一定要包含抽象方法
若類中包含抽象方法,給類必須被定義為抽象類
介面
格式: interface {} 介面中的成員修飾符是固定的。 •成員常量:public static final •成員函數:public abstract •發現介面中的成員都是public的。 介面的出現將“多繼承”通過另一種形式體現出來,即“多實現”。
介面的特點
介面是對外暴露的規則。 介面是程式的功能擴展。 介面的出現降低耦合性。 介面可以用來多實現。 類與介面之間是實現關係,而且類可以繼承一個類的同時實現多個介面。 介面與介面之間可以有繼承關係。
介面是抽象類的一種,只包含常量和方法的定義,沒有變數和方法的實現,且其方法都是抽象方法。
用處體現在:
通過介面,實現不相關類的相同行為
通過介面,指明多個類需要實現的方法
通過介面,瞭解對象的交互界面,無需瞭解對象所對應的類
介面的實現: 在類的聲明中用implements子句來表示一個類使用某個介面 類體中可以使用介面中定義的常量,必須實現介面中定義的所有方法 一個類可以實現多個介面,在implements中用逗號隔開 介面類型的使用: 介面作為一種引用類型來使用 任何實現該介面的類的實例,都可以存儲在該介面類型的變數中,通過這些實例,訪問該類介面中的方法。
介面與抽象類
多態
定義:某一類事物的多種存在形態。 例:動物中貓,狗。 貓這個對象對應的類型是貓類型 •貓 x = new 貓(); 同時貓也是動物中的一種,也可以把貓稱為動物。 •動物 y = new 貓(); •動物是貓和狗具體事物中抽取出來的父類型。父類型引用指向了子類對象。
class A {
void callme() {
System.out.println("Inside A's callme()) method");
}
}
class B extends A {
void callme() {
System.out.println("Inside B's callme() method");
}
}
public class Dispatch {
public static void main(String args[]) {
A a = new B(); // 引用子類的實例
a.callme();
}
}
程式中體現: 父類或者介面的引用指向或者接收自己的子類對象。 好處和作用: 多態的存在提高了程式的擴展性和後期可維護性 前提: •需要存在繼承或者實現關係 •要有覆蓋操作
子類繼承父類後,同一個方法有不同的表現
體現在兩個方面:方法重載實現的靜態多態性(編譯時多態),方法重寫實現的動態多態性(運行時多態)
重寫方法的調用原則:子類重寫父類的方法,調用子類方法;反之,調用父類的方法
多態的特點
成員函數: •編譯時:要查看引用變數所屬的類中是否有所調用的成員。 •在運行時:要查看對象所屬的類中是否有所調用的成員。 成員變數: •只看引用變數所屬的類。
多態指是的子類對象可以直接賦給父類變數,但運行時依然表現出子類的行為特征
多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。 多態性語言具有靈活、抽象、行為共用、代碼共用 的優勢,很好的解決了應用程式函數同名問題。總的來說,方法的重寫、重載與動態鏈接構成多態性。 Java引入多態的概念原因之一就是彌補 類的單繼承帶來的功能不足。(為規避C++中多繼承造成的複雜繼承問題,java採用單繼承。)
動態鏈接——對於父類中定義的方法,如果子類中重寫了該方法,那麼父類類型的引用將會調用子類中的這個方法,這就是動態鏈接。
註意:繼承與重載:一是子類與父類的關係,二是重載方法的調用問題。
子類對象可以直接當成父類對象使用,但反過來就不可以。舉例來說,人是父類,學生是人的子類, 所以學生對象一定具備人對象的屬性,但是人對象就未必具有學生對象的特性。 所以學生對象可以當做人對象來使用,但是人對象就不能當做學生對象使用。 註意當把子類對象當成父類對象使用時,子類對象將失去所有的子類特性, 只保留與父類同名的屬性和方法(同名方法不僅是函數名相同,而且參數類型也要一樣,否則不予 保留)。此時可以對父類方法進行重寫。
一個類中如果定義了重載的方法,則系統在調用方法時,會根據參數的類型自動選擇調用合適的方法。
內部類
將一個類定義在另一個類的裡面,對裡面那個類就稱為內部類(內置類,嵌套類)。 訪問特點: •內部類可以直接訪問外部類中的成員,包括私有成員。 •而外部類要訪問內部類中的成員必須要建立內部類的對象。
內部類的位置
內部類定義在成員位置上 •可以被private static成員修飾符修飾。 •被static修飾的內部類只能訪問外部類中的靜態成員。 內部類定義在局部位置上 •也可以直接訪問外部類中的成員。 •同時可以訪問所在局部中的局部變數,但必須是被final修飾的。
匿名內部類
就是內部類的簡化寫法。 前提: •內部類可以繼承或實現一個外部類或者介面。 格式為: •new 外部類名或者介面名(){覆蓋類或者介面中的代碼,(也可以自定義內容。)} 簡單理解: •就是建立一個帶內容的外部類或者介面的子類匿名對象。
什麼時候使用匿名內部類呢? 通常在使用方法是介面類型參數,並該介面中的方法不超過三個時,可以將匿名內部類作為參數傳遞。 增強閱讀性。
匿名內部類示例: abstract class A { abstract public void fun1(); } class Outer { public static void main(String[] args) { new Outer().callInner(new A() { public void fun1() { System.out.println("implement for fun1"); } }); } public void callInner(A a) { a.fun1(); } }
異常
異常的體系 •Throwable •Error •通常出現重大問題如:運行的類不存在或者記憶體溢出等。 •不編寫針對代碼對其處理 •Exception
|