筆記四 Java 面向對象對象的三大特性(2)
文章目錄
1. 封裝
含義:隱藏類的實現細節,讓使用者只能通過程序員規定的方法來訪問數據
1.1 訪問控制符
public : 可以被同一個項目中所有類訪問,具有項目可見性,這是最大的訪問權限
private :成員變量和方法只能在類內被訪問,具有類可見性.
default :成員變量和方法只能被同一個包裏的類訪問,具有包可見性
protected :可以被同一個包中的類訪問,被同一個項目中不同包中的子類訪問
作用 | 同一類 | 子類 | package | 其他包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
private | √ | ✗ | ✗ | ✗ |
protected | √ | √ | √ | ✗ |
default | √ | ✗ | √ | ✗ |
package note4.access;
/**
* @author Calvin
* @titile: 訪問控制符
* @date 2019/2/21
* @since 1.0
*/
public class PrivateSymbol {
/**
* private 修飾的成員變量,只能適用於當前類
*/
private String message = "PRIVATE_ACCESS_CONTROLLER_SYMBOL";
/**
* pirvate 修飾的方法,只能適用於當前類
* @param message
* @return
*/
private void println(String message){
System.out.println(message);
};
}
// 跨類訪問 -> 異常信息 -> prntln(java.lang.String)' has private access in 'note4.access.PrivateSymbol
package note4.access;
/**
* @author Calvin
* @titile: 受保護訪問控制符
* @date 2019/2/21
* @since 1.0
*/
public class ProtectedSymbol {
protected String message= "PROTECTED_ACCESS_CONTROLLER_SYMBOL";
protected void println(String message){
System.out.println(message);
}
}
/**
* 在同一個包下訪問 protected
*/
class AccessProtectdBySamePackage{
public static void main(String[] args) {
/**
* protected -> 可以被同一個包中的類訪問
*/
ProtectedSymbol protectedSymbol = new ProtectedSymbol();
protectedSymbol.println(protectedSymbol.message);
}
}
/**
* 通過子類訪問父類 protected
*/
class AccessProtectdByMyChild extends ProtectedSymbol {
public static void main(String[] args) {
/**
* protected -> 可以通過子類訪問父類
*/
ProtectedSymbol protectedSymbol = new ProtectedSymbol();
protectedSymbol.println(protectedSymbol.message);
}
}
// 在不同包訪問Protected-> 異常報錯信息 message' is not public in 'note4.access.ProtectedSymbol'. Cannot be accessed from outside package
package note4.access;
/**
* @author Calvin
* @titile: 默認訪問控制控制符
* @date 2019/2/21
* @since 1.0
*/
public class DefaultSymbol {
String message= "DEFAULT_ACCESS_CONTROLLER_SYMBOL";
void println(String message){
System.out.println(message);
}
}
/**
* 在同一個包下訪問 Default
*/
class AccessDefaultBySamePackage{
public static void main(String[] args) {
/**
* default -> 可以被同一個包中的類訪問
*/
DefaultSymbol defaultSymbol = new DefaultSymbol();
defaultSymbol.println(defaultSymbol.message);
}
}
/**
* 通過子類訪問父類 default
*/
class AccessDefaultByMyChild extends DefaultSymbol {
public static void main(String[] args) {
/**
* Default -> 可以通過子類訪問父類
*/
DefaultSymbol defaultSymbol = new DefaultSymbol();
defaultSymbol.println(defaultSymbol.message);
}
}
// 在不同包訪問Default -> 異常報錯信息 message' is not public in 'note4.access.DefaultSymbol'. Cannot be accessed from outside package
1.2 具體步驟
1.修改屬性的可見性來限制對屬性的訪問
2.爲每個屬性創建一對賦值(setter)方法和取值(getter)方法,用於對這些屬性的存取
3.在賦值方法中,加入對屬性的存取控制語句
package note4.access;
/**
* @author Calvin
* @titile: 訪問控制符操作步驟
* @date 2019/2/21
* @since 1.0
*/
public class AccessSymbolOperation {
// 修改屬性的可見性來限制對屬性的訪問
private String message;
private String title;
public AccessSymbolOperation(String message, String title) {
this.message = message;
this.title = title;
}
// 爲每個屬性創建一對賦值(setter)方法和取值(getter)方法,用於對這些屬性的存取
public String getMessage() {
return message;
}
public void setMessage(String message) {
// 在賦值方法中,加入對屬性的存取控制語句
this.message = message;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
2. 繼承
2.1 定義
a.子類繼承父類屬性和方法,但私有屬性和私有方法不能繼承
b.通過關鍵字 extends
2.2 作用
代碼重用,代碼複用
2.3 注意事項
a. 一個類 -> 繼承一個父類 (一個孩子只有一個父親)
b. 一個類 -> 多個子類 (一個父親有多個孩子)
c. 構造方法不繼承
d. 沒有訪問權限的成員不繼承
e. 靜態成員不繼承
package note4.extend;
/**
* @author Calvin
* @titile: 父類
* @date 2019/2/21
* @since 1.0
*/
public class Father {
/**
* 基因
*/
protected String gene;
/**
* 名稱
*/
private String name = "Calvin";
/**
* 健康身體
*/
public void haveHealthBody(){
System.out.println("HEALTH_BODY");
}
}
package note4.extend;
/**
* @author Calvin
* @titile:
* @date 2019/2/21
* @since 1.0
*/
public class Children extends Father{
// 不能繼承父類私有屬性 name' has private access in 'note4.extend.Father'
// private String name = super.name;
/**
* 繼承父親的基因
*/
private String gene = super.gene;
/**
* 繼承父類健康身體
*/
private void extendFatherHealthBody(){
super.haveHealthBody();
}
}
3. 多態
3.1 定義
多態指的是編譯器(申明變量是)和運行期(創建對象後)表現爲不同的形態(數據類型)
3.2 注意事項
a. 繼承的存在(繼承是多態的基礎,沒有繼承就沒有多態)
b. 子類重寫父類的方法(多態下調用子類重寫的方法)
c. 父類引用變量指向子類對象(子類到父類的類型轉換)
3.3 子類轉換成父類規則
- 將一個父類的引用指向一個子類的對象,稱爲向上轉型(upcastiog),自動進行類型轉換.
- 此時通過父類引用調用的方法是子類覆蓋或繼承父類的方法,不是父類的方法.
- 此時通過父類引用變量無法調用子類特有的方法
- 如果父類要調用子類的特有方法就得將一個指向子類對象的父類引用賦給一個子類的引用,稱爲向下轉型,此時必須進行強制類型轉換
a.向上轉型:父類 = 子類實例化() ========== 1.子類和父類確立關係 ============== 2.系統自動完成 作用:父類可以接受來自不同子類的實現方式(覆蓋父類方法的子類方法)。 例如:B(fun1)、C(fun1) 繼承 A (fun1) ====>> 如何子類如何獲取覆蓋fun1 =====>>fun(new B) || fun(new C)==========>> fun(A a){ a.fun1()}=========>>向上轉型:子類可以獲取到子類覆蓋的對應方法。
b.向下轉型: 子類 = 父類實例化() ========== 1.無法確立關係,需要先進行確立關係(向上轉型後),才能進行轉換。================== 否則,強制轉換(轉換異常) 作用:可以獲取子類自定義的方法。
package note4.manystate;
/**
* 父類
*/
public class Parent {
/**
* fun1()
**/
public void fun1() {
System.out.println("【執行的是父類fun1】");
}
/**
* fun2()
**/
public void fun2() {
this.fun1();
}
}
/**
* 子類A繼承父類
*/
class Children1 extends Parent {
/**
* 重載 -> 父類fun1()
*/
@Override
public void fun1() {
System.out.println("【執行的是子類A fun1】");
}
/**
* 自定義方法fun3
*/
public void fun3() {
System.out.println("【執行的是子類A fun3】");
}
}
/**
* 子類B繼承父類
*/
class Children2 extends Parent {
/**
* 重載 -> 父類fun1()
*/
@Override
public void fun1() {
System.out.println("【執行的是子類B fun1】");
}
/**
* 自定義方法fun4
*/
public void fun4() {
System.out.println("【執行的是子類A fun4】");
}
}
/**
* Created by Calvin on 2018/6/5
* 向上轉型
* 父類 = 子類實例化
*/
class Upcasting {
public static void main(String[] args) {
Children1 children = new Children1();
Parent parent = children; // 向上轉型:父類 = 子類實例化
parent.fun1(); // 【執行的是子類A fun1】
}
}
/**
* Created by Calvin on 2018/6/5
* 向下轉型
* 子類 = 父類實例化
* ps:
* 1.向下轉型,必須先向上轉型(確立父子關係),才能進行向下轉型。
* 2.如果單一的向下轉型,報錯:轉換異常。
*/
class Downcasting {
public static void main(String[] args) {
Parent parent = new Children1(); // 向上轉型(確立關係)
Children1 children = (Children1) parent; // 向下轉型
children.fun1(); // 調用方法被複寫 【執行的是子類A fun1】
children.fun2(); // 調用父類的方法 【執行的是父類fun1】
children.fun3(); // 調用子類自定義的方法 【執行的是子類A fun3】
}
}
/**
* Created by Calvin on 2018/6/6
* 向上轉型功能代碼
*/
class PolymorphicFunction {
/********************************************* 不使用多態 ****************************/
/**
* 缺點: 每一拓展子類,每一次都fun()方法都要重載一次。
* A==>>B,C,D
*/
public void unUsedPolymorphic() {
unfun(new Children1());
unfun(new Children2());
}
public void unfun(Children1 children1) {
children1.fun1();
}
public void unfun(Children2 children2) {
children2.fun1();
}
/********** 使用多態: 實現父類下任意子類對象,並調用方法 ***********************/
public void usePolymorphic() {
// 父類的通用方法 fun1 -> 只要向上轉型實例其中一個子類 -> 就能獲取到子類重載父類的方法 -> 使用的是子類的方法
fun(new Children1());
fun(new Children2());
}
public void fun(Parent parent) {
parent.fun1();
}
}