細說面向對象三大特徵

面向對象特徵之封裝性

1. 爲何要引入封裝性?

咱們程序設計追求「高內聚,低耦合」java

  • 高內聚:類的內部數據操做細節本身完成,不容許外部干涉面試

  • 低耦合:僅對外暴露少許的方法用於使用。數據庫

隱藏對象內部的複雜性,只對外公開簡單的接口。便於外界調用,從而提升系統的可擴展性、可維護性。通俗的說,把該隱藏的隱藏起來,該暴露的暴露岀來。這就是封裝性的設計思想。this

2. 問題引入:

當咱們建立一個類的對象之後,咱們能夠經過"對象.屬性"的方式,對對象的屬性進行賦值。這裏,賦值操做要受到屬性的數據類型和存儲範圍的制約。除此以外,沒其餘制約條件。可是,在實際問題中,咱們每每須要給屬性賦值加入額外的限制條件。這個條件就不能在屬性聲明時體現,咱們只能經過方法進行限制條件的添加。(好比:setLegs()同時,咱們須要避免用戶再使用"對象.屬性"的方式對屬性進行賦值。則須要將屬性聲明爲私有的(private).spa

此時,針對於屬性就體現了封裝性。設計

3. 封裝性思想具體的代碼體現:

體現一:code

將類的屬性xxx私化(private),同時,提供公共的(public)方法來獲取(getXxx)和設置(setXxx)此屬性的值對象

private double radius;
public void setRadius(double radius){
	this.radius = radius;
}
public double getRadius(){
	return radius;
}

體現二:不對外暴露的私有的方法繼承

體現三:單例模式(將構造器私有化)接口

體現四:若是不但願類在包外被調用,能夠將類設置爲缺省的。

4. Java規定的四種權限修飾符

經過對不一樣的方法屬性設置不一樣的權限修飾符來達到對類進行封裝的目的。

4.1 權限從小到大順序爲:private < 缺省 < protected < public

4.2 具體的修飾範圍:

修飾符 類內部 同一個包 不一樣包的子類 同一個工程
private Yes      
(缺省) Yes Yes    
protected Yes Yes Yes  
public Yes Yes Yes Yes

4.3 權限修飾符可用來修飾的結構說明:

4種權限均可以用來修飾類的內部結構:屬性、方法、構造器、內部類

修飾類的話,只能使用:缺省、public

面向對象特徵之繼承性

1.爲何要有類的繼承性?(繼承性的好處)

  • 減小了代碼的冗餘,提升了代碼的複用性
  • 便於功能的擴展
  • 爲以後多態性的使用,提供了前提

image-20200327224109229

2.繼承性的格式:

class A extends B{}
 *    A:子類、派生類、subclass
 *    B:父類、超類、基類、superclass

判斷是否要進行繼承:A is a B,若成立,則B繼承A

3.子類繼承父類之後有哪些不一樣?

3.1體現:一旦子類A繼承父類B之後,子類A中就獲取了父類B中聲明的全部的屬性和方法。

特別的,父類中聲明爲private的屬性或方法,子類繼承父類之後,仍然認爲獲取了父類中私的結構。只由於封裝性的影響,使得子類不能直接調用父類的結構而已。

3.2 子類繼承父類之後,還能夠聲明本身特有的屬性或方法:實現功能的拓展。

子類和父類的關係,不一樣於子集和集合的關係。

extends:延展、擴展

4. Java中繼承性的說明

  1. 一個類能夠被多個子類繼承。
  2. Java中類的單繼承性:一個類只能有一個父類
  3. 子父類是相對的概念。
  4. 子類直接繼承的父類,稱爲:直接父類。間接繼承的父類稱爲:間接父類
  5. 子類繼承父類之後,就獲取了直接父類以及所間接父類中聲明的屬性和方法

image-20200331090341980

5. java.lang.Object類的理解

是Java中全部類的父類,相似於二叉樹中的根節點,定義了一些通用的方法。

  1. 若是咱們沒顯式的聲明一個類的父類的話,則此類繼承於java.lang.Object類
  2. 所的java類(除java.lang.Object類以外都直接或間接的繼承於java.lang.Object類
  3. 意味着,所的java類具備java.lang.Object類聲明的功能。
  4. java.lang.Object類中定義的一些方法
方法名 類型 描述
public Object() 構造方法 構造器
public boolean equals( Object obj) 普通方法 對象比較
public int hashCode() 普通方法 獲取Hash碼
public String toString() 普通方法 對象打印時調用

面向對象的特徵之多態性

1. 多態性的理解:

能夠理解爲一個事物的多種形態。好比數據庫的鏈接方式,咱們定義好了數據庫的鏈接,也規定了鏈接時的步驟,可是咱們並不知道用戶會採用什麼數據庫,在沒有多態之前咱們只能針對不一樣的數據庫寫不一樣的鏈接方法,而有了多態之後咱們只須要定義好數據庫的類並書寫好鏈接方法,讓全部的數據庫繼承數據庫類並重寫數據庫鏈接方法。這樣咱們在調用的時候只須要經過聲明數據庫類並指向數據庫的子類的方式,*(即數據庫類的引用指向繼承了數據庫類的具體實現類的對象)*就能夠進行數據庫鏈接。而不是須要針對不一樣的數據庫書寫不一樣的鏈接方式。

2. 何爲多態性:

對象的多態性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)

編譯時和運行時類型不一致,產生了多態

舉例:

Person p = new Man();
Object obj = new Date();

3. 多態性的使用:虛擬方法調用

有了對象的多態性之後,咱們在編譯期,只能調用父類中聲明的方法,但在運行期,咱們實際執行的是子類重寫父類的方法。

總結:編譯,看左邊;運行,看右邊。

對象的多態:在Java中,子類的對象能夠替代父類的對象使用

  • 一個變量只能有一種肯定的數據類型
  • 一個引用類型變量可能指向(引用)多種不一樣類型的對象

4.多態性的使用前提:

① 類的繼承關係 ② 方法的重寫

5.多態性的應用舉例:

舉例一:
	public void func(Animal animal){//Animal animal = new Dog();
		animal.eat();
		animal.shout();
	}
舉例二:
public void method(Object obj){
		
	}
舉例三:
class Driver{
	
	public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
		//規範的步驟去操做數據
//		conn.method1();
//		conn.method2();
//		conn.method3();
		
	}
	
}

6. 多態性使用的注意點:

對象的多態性,只適用於方法,不適用於屬性(編譯和運行都看左邊)

個引用類型變量若是聲明爲父類的類型,但實際引用的是子類對象,那麼該變量就不能再訪問子類中添加的屬性和方法

小結:

多態的做用:提升了代碼的通用性,常稱做接口重用

前提:
須要存在繼承或者實現關係
有方法的重寫

成員方法:
編譯時:要查看引用變量所聲明的類中是否有所調用的方法
運行時:調用實際new的對象所屬的類中的重寫方法

成員變量:
不具有多態性,只看引用變量所聲明的類

7. 關於向上轉型與向下轉型:

7.1 向上轉型:多態

7.2 向下轉型:

7.2.1 爲何使用向下轉型:

有了對象的多態性之後,內存中其實是加載了子類特有的屬性和方法的,可是因爲變量聲明爲父類類型,致使編譯時,只能調用父類中聲明的屬性和方法。子類特有的屬性和方法不能調用。如何才能調用子類特的屬性和方法?使用向下轉型。

7.2.2 如何實現向下轉型:

使用強制類型轉換符:()

Person p = new Man();

Man m1=(Man)p2;//向下轉型

7.2.3 使用時的注意點:

① 使用強轉時,可能出現ClassCastException的異常。 ② 爲了不在向下轉型時出現ClassCastException的異常,咱們在向下轉型以前,先進行instanceof的判斷,一旦返回true,就進行向下轉型。若是返回false,不進行向下轉型。

只有對象A是B的子類實例化對象或者在下層的子類,才能向下轉型

7.2.4 instanceof的使用:

① a instanceof A :判斷對象a是不是類A的實例。若是是,返回true;若是不是,返回false。

② 若是 a instanceof A返回true,則 a instanceof B也返回true.其中,類B是類A的父類。

③ 要求a所屬的類與類A必須是子類和父類的關係,不然編譯錯誤。

p instanceif Man//左邊是變量名,右邊是類的類型

7.2.5 圖示:

image-20200328170736290

8.面試題:

8.1 談談你對多態性的理解?

  1. 實現代碼的通用性。
  2. 舉例:
    • Object類中定義的public boolean equals(Object obj){ }
    • JDBC:使用java程序操做(獲取數據庫鏈接、CRUD)數據庫(MySQL、Oracle、DB二、SQL Server)
    • 抽象類、接口的使用確定體現了多態性。(抽象類、接口不能實例化)

8.2 多態是編譯時行爲仍是運行時行爲?

運行時行爲

9.練習

class Base {
	int count = 10;

	public void display() {
		System.out.println(this.count);
	}
}

class Sub extends Base {
	int count = 20;

	public void display() {
		System.out.println(this.count);
	}
}

public class FieldMethodTest {
	public static void main(String[] args) {
		Sub s = new Sub();
		System.out.println(s.count);//20
		s.display();//20
		
		Base b = s;//多態性
		//==:對於引用數據類型來說,比較的是兩個引用數據類型變量的地址值是否相同
		System.out.println(b == s);//true
		System.out.println(b.count);//10
		b.display();//20
	}
}

強調:

  1. 若子類重寫了父類方法,就意味着子類裏面定義的方法完全覆蓋了父類裏的同名方法,系統將不可能把父類裏的方法轉移到子類中:編譯看左邊,運行看右邊
  2. 對於實例變量則不存在這樣的現象,即便子類裏定義了與父類徹底相同的實例變量,這個實例變量依然不可能覆蓋父類中定義的實例變量:編譯運行都看左邊
相關文章
相關標籤/搜索