第11天面向對象

1.1 接口概念:

接口是功能的集合,同樣可看做是一種數據類型,是比抽象類更爲抽象的”類”。
接口只描述所應該具備的方法,並沒有具體實現,具體的實現由接口的實現類(相當於接口的子類)來完成。這樣將功能的定義與實現分離,優化了程序設計。
請記住:一切事物均有功能,即一切事物均有接口。

1.2接口的定義:

接口定義時需要使用interface關鍵字。
定義接口所在的仍爲.java文件,雖然聲明時使用的爲interface關鍵字的編譯後仍然會產生.class文件。
定義格式: 接口中的權限被固定爲:public權限。Public寫或者不寫,都是public。

public interface 接口名 {   
	抽象方法1;
	抽象方法2;
	抽象方法3;
}
  • 接口中的方法均爲公共訪問的抽象方法。
  • 接口中無法定義普通的成員變量。

1.3 類實現接口:

類與接口的關係爲實現關係,即類實現接口。實現使用implements。
其他類(實現類)實現接口後,就相當於聲明:”我應該具備這個接口中的功能”。實現類仍然需要重寫方法以實現具體的功能。

格式:
classimplements 接口 {
	重寫接口中方法
} 
  • 接口中定義功能,當需要具有該功能時,可以讓類實現該接口,只聲明瞭應該具備該方法,是功能的聲明。
  • 在具體實現類中重寫方法,實現功能,是方法的具體實現。
  • 類是現實事物的描述,接口是功能的集合。

1.4 接口中成員的特點:

  • 1、接口中可以定義變量,但是變量必須有固定的修飾符修飾,public static final
    所以接口中的變量也稱之爲常量,其值不能改變。(必須是常量,不寫或者選擇性也是默認添加。常量被靜態修飾,可以被類名直接調用,被接口的名字直接調用)
  • 2、接口中可以定義方法,方法也有固定的修飾符,public abstract(可以不寫或者選擇性書寫)
  • 3、接口不可以創建對象。
  • 4、子類必須覆蓋掉接口中所有的抽象方法後,子類纔可以實例化。否則子類是一個抽象類。

1.5 接口的多實現:

接口最重要的體現:解決多繼承的弊端。將多繼承這種機制在java中通過多實現完成了。

1.6 類繼承類同時實現接口:

當一個類已經繼承了一個父類,它又需要擴展額外的功能,這時接口就派上用場了。
子類通過繼承父類擴展功能,通過繼承擴展的功能都是子類應該具備的基礎功能。如果子類想要繼續擴展其他類中的功能呢?這時通過實現接口來完成。

接口的出現避免了單繼承的侷限性。父類中定義的事物的基本功能。接口中定義的事物的擴展功能。

1.7 接口的多繼承:

多個接口之間可以使用extends進行繼承。

interface Fu1{
	void show();
}
interface Fu2{
	void show1();
}
interface Fu3{
	void show2();
}
interface Zi extends Fu1,Fu2,Fu3{
	void show3();
}

在開發中如果多個接口中存在相同方法,這時若有個類實現了這些接口,那麼就要實現接口中的方法,由於接口中的方法是抽象方法,子類實現後也不會發生調用的不確定性。

1.8 接口的思想:

總結:接口在開發中的它好處
1、接口的出現擴展了功能。
2、接口其實就是暴漏出來的規則。
3、接口的出現降低了耦合性,即設備與設備之間實現瞭解耦。

1.9 接口和抽象的區別:

相同點:

  • 都位於繼承的頂端,用於被其他類實現或繼承;
  • 都不能直接實例化對象;
  • 都包含抽象方法,其子類都必須覆寫這些抽象方法;

區別:

  • 抽象類爲部分方法提供實現,避免子類重複實現這些方法,提高代碼重用性;接口只能包含抽象方法;
  • 一個類只能繼承一個直接父類(可能是抽象類),卻可以實現多個接口;(接口彌補了Java的單繼承)
  • 抽象類是這個事物中應該具備的內容, 繼承體系是一種 is…a 關係
  • 接口是這個事物中的額外內容,繼承體系是一種 like…a關係

二者的選用:

  • 優先選用接口,儘量少用抽象類;
  • 需要定義子類的行爲,又要爲子類提供共性功能時才選用抽象類;

2.1 多態概述:

Java作爲面向對象的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的對象便既是Student,又是Person。
Java中多態的代碼體現在一個子類對象(實現類對象)既可以給這個子類(實現類對象)引用變量賦值,又可以給這個子類(實現類對象)的父類(接口)變量賦值。

最終多態體現爲父類引用變量可以指向子類對象。
多態的前提是必須有子父類關係或者類實現接口關係,否則無法完成多態。
在使用多態後的父類引用變量調用方法時,會調用子類重寫後的方法。

2.2 多態的定義與使用格式:

多態的定義格式:就是父類的引用變量指向子類對象
父類類型或者接口類型 變量名 = new 子類類型();

變量名.方法名();

  • 普通類多態定義的格式:父類 變量名 = new 子類();
class Fu {}
class Zi extends Fu {}
	//類的多態使用
Fu f = new Zi();
  • 抽象類多態定義的格式:抽象類 變量名 = new 抽象類子類();
abstract class Fu {
        public abstract void method();
}
class Zi extends Fu {
   public void method(){
   	      System.out.println(“重寫父類抽象方法”);
   }
}
//類的多態使用
Fu fu= new Zi();
  • 接口多態定義的格式:接口 變量名 = new 接口實現類();
interface Fu {
   	     public abstract void method();
}
class Zi implements Fu {
   	     public void method(){
             System.out.println(“重寫接口抽象方法”);
         }
}
//接口的多態使用
Fu fu = new Zi();

注意事項:
同一個父類的方法會被不同的子類重寫。在調用方法時,調用的爲各個子類重寫後的方法。
當變量名指向不同的子類對象時,由於每個子類重寫父類方法的內容不同,所以會調用不同的方法。

2.3 多態-成員的特點:

class Fu {
	int num = 4;
}
class Zi extends Fu {
	int num = 5;
}
class Demo {
	public static void main(String[] args) 	{
		Fu f = new Zi();
		System.out.println(f.num);
		Zi z = new Zi();
		System.out.println(z.num);
	}
}

多態成員變量:編譯和運行全看父類。
當子父類中出現同名的成員變量時,多態調用該變量時:

  • 編譯時期:參考的是引用型變量所屬的類中是否有被調用的成員變量。沒有,編譯失敗。
  • 運行時期:也是調用引用型變量所屬的類中的成員變量。

簡單記:編譯和運行都參考等號的左邊。編譯運行看左邊。

多態出現後會導致子父類中的成員方法有微弱的變化。

class Fu {
	int num = 4;
	void show()	{
		System.out.println("Fu show num");
	}
}
class Zi extends Fu {
	int num = 5;
	void show()	{
		System.out.println("Zi show num");
	}
}
class Demo {
	public static void main(String[] args) 	{
		Fu f = new Zi();
		f.show();
	}
}

多態成員方法:編譯看父類,運行看子類。

  • 編譯時期:參考引用變量所屬的類,如果沒有類中沒有調用的方法,編譯失敗。
  • 運行時期:參考引用變量所指的對象所屬的類,並運行對象所屬類中的成員方法。
  • 簡而言之:編譯看左邊,運行看右邊。

2.4 instanceof關鍵字:

通過instanceof關鍵字來判斷某個對象是否屬於某種數據類型。
使用格式:
boolean b = 對象 instanceof 數據類型;

2.5多態-轉型:

多態的轉型分爲向上轉型與向下轉型兩種:

  • 向上轉型:當有子類對象賦值給一個父類引用時,便是向上轉型,多態本身就是向上轉型的過程。
    使用格式:
父類類型  變量名 = new 子類類型();
如:Person p = new Student();
  • 向下轉型:一個已經向上轉型的子類對象可以使用強制類型轉換的格式,將父類引用轉爲子類引用,這個過程是向下轉型。如果是直接創建父類對象,是無法向下轉型的!
子類類型 變量名 = (子類類型) 父類類型的變量;:Student stu = (Student) p;  //變量p 實際上指向Student對象

2.6 多態的好處與弊端:

當父類的引用指向子類對象時,就發生了向上轉型,即把子類類型對象轉成了父類類型。向上轉型的好處是隱藏了子類類型,提高了代碼的擴展性。
但向上轉型也有弊端,只能使用父類共性的內容,而無法使用子類特有功能,功能有限制。

總結:
什麼時候使用向上轉型:
當不需要面對子類類型時,通過提高擴展性,或者使用父類的功能就能完成相應的操作,這時就可以使用向上轉型。
什麼時候使用向下轉型:
當要使用子類特有功能時,就需要使用向下轉型。

向下轉型的好處:可以使用子類特有功能。
弊端是:需要面對具體的子類對象:在向下轉型時容易發生ClassCastException類型轉換異常。在轉換之前必須做類型判斷。

如:if( !a instanceof Dog){…}

總結下封裝、繼承、多態的作用:

  • 封裝:把對象的屬性與方法的實現細節隱藏,僅對外提供一些公共的訪問方式
  • 繼承:子類會自動擁有父類所有可繼承的屬性和方法。
  • 多態:配合繼承與方法重寫提高了代碼的複用性與擴展性;如果沒有方法重寫,則多態同樣沒有意義。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章