java物件導向 - aa123981934/java GitHub Wiki
物件導向程式OOP
物件導向是一種抽象且擬人化的程式設計
是一個將程式抽象化且各自獨立的物件
物件內描述的資料稱作 屬性
用來描述物件內部的行為稱作 方法
因此可以說,物件是一個相關屬性(資料)與方法(函式)的組合
物件導向程式中,物件(Object)
就是某個類別(Class)
的實體,在java語言中,產生一個物件實體就可以使用new
這個關鍵字
而所有的類別可透過繼承關係相互呼叫、引用與傳遞訊息,形成一個彼此連結且有層次的結構
java物件導向程式語言的2個精神與3個特徵如下:
2個精神:
-
抽象化(Abstraction)
:物件抽象化是有助於瞭解並實際掌握物件的內容。 -
繼承(Inheritance)
:抽象化是指物件被良好的定義及描述,繼承則是賦予程式能重複使用物件以增加延展性。
3個特徵:
-
繼承(Inheritance)
-
封裝(Encapsulation)
-
多形(Polymorphism)
何謂類別?
類別是物件的藍圖,也是物件的實體基礎。類別內部定義了使用者的資料型態,在JAVA中類別的宣告中引用的class
這個關鍵字
_
_
java類別定義的語法 / 宣告方法
[存取修飾字 修飾語] + 宣告類別(class) + 類別名稱{
//定義屬性及方法的敘述句
}
類別的存取修飾字若為 public,則該類別名稱必須與類別檔名相同,例如:app.java,類別存取的檔案名稱就必須為app.java(注意大小寫)
_
_
修飾語可以是static、abstract或者final等型態的指定字
MyClass.java 類別定義
【public】 class MyClass{
//MyClass類別的內容包含了屬性以及方法描述
}
一般(外部)類別
,的存取修飾字只能是public與default / package(無修飾字)
如果是內部類別(在類別中定義一個類別)
,則可以使用public、protected、default、private來修飾
_
_
物件屬性
屬性是物件的資料,也可以說是變數,可手動給初始值,也可以不給定初始值,在宣告物變數時候,不使用static
來修飾變數,而且變數必須宣告在class
內。
宣告方法
[存取修飾字] + [static] + 資料型別 + 屬性名稱
有加上
static
的稱為「類別變數」
,反之稱「物件變數」
static
String name = "狗狗" <---類別變數String name= "貓貓" <---物件變數
public class MyClass{
int i=100; //物件變數(不加static)
static int a=200; //類別變數
}
物件變數是由物件獨立維護,彼此不受干擾。static
類別變數是屬於類別的變數,因為static也是一個類別,但是可以由該類別在記憶體空間中new
出來的物件共享使用
在權限充足情況下仍可以合法使用,有點類似全域變數概念
宣告在方法內的變數名稱稱為區域變數
public class app {
int i =100; //物件變數
static int b =200; //類別變數
void sMethod(String c){ //c為sMethod()的區域變數
int j =10; //J為sMethod的區域變數
}
static int z =20; //
方法中不可以定義static變數
,否則會編譯錯誤
static 關鍵字用於定義類別層級的變數(靜態變數)和方法(靜態方法)
物件方法
物件的方法是一個描述類別內部的行為,也是外部存取物件內部資料的方法,因物件通常不允許外界直接
存取其內部資料或變數,只能夠過相對應方法以提供外界存取之用
宣告方式
[存取修飾字] + [static] + 回傳值 + 方法名稱(參數列) + {}
有加上
static
稱為「類別方法」
,反之稱「物件方法」
static void skill() {} //類別方法
void skillb() {} //物件方法
宣告物件方法不使用static來修飾方法,而且必須宣告於class層級內
public calss abc{
void aMethod() { //aMethod為物件方法不加static
} static void bMethod(){ //bMethod為類別方法
}
}
不論是物件還是類別方法,方法內不可以再定義其他方法,方法是一段獨立的程式碼區塊,否則會編譯錯誤 _
_
在myMethod()方法中內又定義了innerMethod()了一個方法,將會錯誤!!!
如何建立物件實體?
類別內定義了許多資料型態與宣告,宣告類別
、內部類別
、類別(靜態)方法
、物件(實體)方法
、物件(實體)變數
、類別(靜態)變數
簡單來說,類別定義宣告出來的實體就是物件
宣告方式
類別名稱 物件(變數)名稱 = new 類別名稱();
類別名稱 物件(變數)名稱;
物件(變數)名稱 = new 類別名稱();
由上可知,物件其實就是類別所宣告建立出來的。
類別名稱 物件(變數)名稱 (假設物件變數=t) 因為要實例化,所以宣告物件名稱為t
new 類別名稱() 利用new關鍵字在記憶體中擷取一個區塊已配置該物件
分配記憶體空間: 當你使用new
關鍵字時,Java 程式碼會在記憶體中為新的物件實例分配足夠的空間。這個空間將包含該物件的所有屬性和方法。
利用物件變數抓取其屬性與方法的表示:
物件變數名稱.屬性
:抓取物件的屬性內容
物件變數名稱.方法()
:執行物件方法
建構子
在記憶體中配置一個存放物件的區塊之外,同時也會執行建構子函式。是物件建立所執行的第一個函式
通常設定物件被引用前,應所載入的一些設定以初始化內部物件狀態,簡單來說就是有沒有給予參數
建構子在宣告時有兩個特性:
-
建構子
沒有回傳值
-
建構子
名稱
必須與類別名稱
相同
宣告語法
存取權限 類別名稱(參數列)
public class
test
{
public test()
{)}
一般建構子
帶有參數的建構子
-
在使用帶有參數的建構子時,你在呼叫 new 關鍵字來建立物件時,必須提供相同的參數。
-
這樣 Java 才知道應該使用哪個建構子來初始化物件。如果你使用了帶有參數的建構子,但在建立物件時沒有提供相同的參數,將會導致編譯錯誤。
預設建構子
類別(class)裡面一定要有建構子!!!!,在撰寫class時必須定義類別的建構子,如果程式中沒有明確定義建構子,那系統在編譯的時候會自動在該類別加上建構子
所加上的建構子稱為預設建構子
預設建構子五大特點:
-
每一個 class 最多只能有一個預設建構子
-
程式中若沒有定義建構子,在編譯時會自動加入,稱預設建構子
-
預設建構子的存取權限與該類別的存取權限相同
-
預設建構子沒有參數列
-
除了初始成員變數或繼承時super()的定義外,預設建構子基本上是沒有其他的程式敘述
語法(編譯器自動生成)
類別的存取權限 類別名稱(){}
static成員與non-static成員
static
成員就是類別成員,包含靜態內類別、類別屬性與類別方法。non-static成員則是物件,即物件屬性與物件方法
法則:
-
在 non-static 成員中可以直接存取 non-static 成員與 static 成員
-
在 static 成員中只允許直接存取 static 成員,若要存取 non-static 成員,必須明確地宣告與創建物件之後再進行存取
存取方式:
-
靜態成員可以直接透過類別名稱存取,而不需要建立物件實例。
-
非靜態成員需要通過建立物件實例才能存取。
初始化:
-
靜態成員在類別載入時初始化,並且只會初始化一次。
-
非靜態成員在建立物件實例時初始化。
資源共享:
-
所有物件實例共享相同的靜態成員,因此修改靜態成員的值會影響到所有實例。
-
每個物件實例都有自己的非靜態成員的副本,因此修改非靜態成員的值只會影響到該物件實例。
使用情境:
-
靜態成員通常用於表示與類別相關的資訊,例如常數、工具方法等。
-
非靜態成員通常用於表示物件的狀態和行為,例如物件的屬性和方法。
範例
編譯後: java: non-static method bmethod() cannot be referenced from a static context
覆寫與超載
所謂覆寫是發生在繼承關係中,子類別實做一個方法來取代父類別所提供的方法,程式會執行子類別的方法,而不執行父類別方法
範例
覆寫的限制與注意事項
-
覆寫是發生在有繼承關係的類別體系中
-
覆寫的方法名稱宣告必須相同
-
若方法有回傳值,其回傳型態必須相同或是原方法傳回值型別的子類別
-
方法中的參數列(不論數量、資料型別及擺放順序)都必須相同
-
存取權限不可小於原方法,在上圖第一個覆寫範例中,原方法amethod()存取權限是
default/packge
,子類別要覆寫覆類別方法時,要宣告方法存取權限必須大於或等於
default
的存取權限,因此可以是default
、protected
、public
,如果是宣告private,因為存取權限比default小,將會編譯錯誤
-
當父類別方法簽章有拋出例外事件,子類別覆寫方法簽章可以選擇是否要拋出,若選擇拋出例外,該例外類別必須:
-
與原方法相同
-
原方法例外事件類別的子類別
-
遮蔽
方法有覆寫機制,屬性也有,屬性的覆寫機制稱為 遮蔽
。
遮蔽機制單純的把父類別屬性覆蓋,但還是可以用super來調用父類別legs的屬性
超載
超載/覆載
,是指同一種方法可以產生不同的實作。呼叫同一個方法可以依傳入不同的參數
,來實作出相異的程式碼,又可分為方法的超載與建構子的超載
方法超載在參數列必須不一樣
的規定下,回傳直型態也可以不一樣
規則
-
方法名稱必須相同
-
參數列必須不相同
-
返回資料型態可相同,可不相同
-
修飾符可不相同
範例
範例中即使傳入的型態都有int
、String
,但是參數列的順序不同,也會視為兩種不同超載方法
封裝
封裝在程式實作中隱藏的過程,透過統一方法或者介面實作,來取得類別中不被允許外部直接存取的內部資料,以維護物件資源的完整性與存取安全,簡單來說就是把類別內的屬性
、方法
給包裝起來
範例
Get與Set
Get功能特性:
- 方法的主要目的是從私有属性中提取值
- 返回值:方法具有傳回值,通常是對應屬性的資料類型,用於傳回該屬性的目前值
- 參數:方法不需要任何參數,因為它只是傳回屬性的值
- 功能:用於獲取對象的私有属性。
Set功能特性:
- 方法是私有属性赋予新的值
- 返回值:方法通常沒有傳回值,即其傳回類型為void
- 参數:方法需要一個參數,與要設定的屬性值的類型相符
- 功能:用于設置對象的私有属性值。
繼承
繼承是指類別物件的資源可以衍伸和重複使用,使用關鍵字extends
來表達類別的繼承關係,當子類別繼承了父類別,可使用父類別中的資源
存取範圍也必須受限父類別的存取修飾字,也就Default
、Protected
、Public
、Private
另外在繼承上java只能接受單一繼承,也就是子類別在定義繼承關係時,但只能對父類別做單一延伸。
範例
[子類別宣告] + extedns + [父類別名稱]
java繼承機制是子類別包含著父類別,因此子類別可以看到父類別,反之不能
繼承關係下的建構子
在JAVA裡面,建構子的繼承關係下的行為是最常出的考題,只要了解建構子在子類別與父類別之間的乎叫行為。
範例
Father與Son在編譯的時候會產生預設建構子,所以必須看成是:
由於Son類別繼承Father類別,所以在預設時java會在Son建構子的第一行預設加入super(),也就是呼叫父類別Father的無帶參數建構子,所以必須看成