面向對象語言的三大特性:封裝、繼承、多态。下面簡單講解java這三大對象的概念:
封裝:java中通過定義類,把屬性,方法封裝進類中,通過類隻有希望使用者通路的功能使用者才能調用。
繼承:java中通過子類繼承父類,子類可以繼承父類功能。
多态:java中父類指向子類,通過動态綁定父類執行個體可以調用子類重寫父類的功能。
剛上大學自學C++時講述面向對象特征時就會列舉這三個概念,java語言也不例外。
(1)多态性概念
多态指程式中一個執行個體變量倒底會指向哪個實作類的引用和該執行個體中的方法到底指向哪個實作類中的方法,隻有在程式運作期間才能決定。是以可以實作不用修改源代碼,可以讓對象指向不同實作類,随着指向不同實作類程式運作時可以根據具體情形調用同一函數實作不同功能,就是多态性。
簡單說:記憶體中引用到底指向哪個方法在運作時才能決定。
(2)java多态實作原理
多态性實作條件繼承,重寫,向上轉型。
靜态綁定&動态綁定:
面向對象語言,多态分為編譯時多态和運作時多态。
編譯時多态是靜态的,主要是指方法的重載,編輯之後會變成兩個不同的函數,運作時通過不同的參數類型或個數進行區分。
運作時多态是動态的,它是通過方法的重寫來實作的。
java繼承口頭禅:
成員變量,靜态方法看左邊;
非靜态方法:編譯看左邊,運作看右邊。
解釋:當父類變量引用子類對象時,父類變量的成員變量和靜态方法與父類是一緻的,非靜态方法,在編譯時是與父類一緻的,運作時卻與子類一緻(重寫)。
注意:java中父類中屬性隻能被隐藏,而不能被覆寫;而對于方法,如果父類和子類存在相同的靜态方法,父類中的靜态方法會被隐藏。java中final類或方法不能被繼承和重寫,是以也不存在多态性,java中普通方法繼承時可以被重寫。
向上轉型&向下轉型(強制類型轉換):
向上轉型(子類轉成父類):
java中父類執行個體可以指向子類引用,此時父類執行個體隻能通路父類中定義的屬性和方法,子類中存在而父類中不存在的方法,該執行個體不能通路。子類如果重寫了父類中的某些方法,父類執行個體調用時使用的是子類中的方法。
注意:向上轉型是類型安全的,因為父類中的方法在子類中都存在(java中子類繼承父類,重寫某些方法,通路修飾符權限不能縮小)。向上轉型還将導緻子類特有屬性方法的缺失(無法調用)。
向下轉型(父類引用轉子類):
父類引用強轉成子類執行個體,向下轉型是類型不安全的,轉型過程中會進行檢查,如果轉型失敗會報ClassCastException錯誤。
(3)多态實作方式
多态有很多經典的例子:動物,形狀等,下面以動物為例。
3.1 繼承和重寫實作多态
public class Animal {
public String Tag = "AnimalTag";
public static String sTag = "SAnimalTag";
public static String getSMethod() {
return "SAMethod";
}
public String getData() {
return "AnimalData";
}
}
public class Dog extends Animal{
public String Tag = "DogAnimalTag";
public static String sTag = "DogSAnimalTag";
public static String getSMethod() {
return "DogSAMethod";
}
@Override
public String getData() {
return "DogData";
}
}
public class Cat extends Animal{
public String Tag = "CatAnimalTag";
public static String sTag = "CatSAnimalTag";
public static String getSMethod() {
return "CatSAMethod";
}
@Override
public String getData() {
return "CatData";
}
}
public static void main(String[] args) {
Animal dog = new Dog();
System.out.println(dog.Tag);
System.out.println(dog.sTag);
System.out.println(dog.getSMethod());
System.out.println(dog.getData());
System.out.println("========================");
Animal cat = new Cat();
System.out.println(cat.Tag);
System.out.println(cat.sTag);
System.out.println(cat.getSMethod());
System.out.println(cat.getData());
System.out.println("========================");
Dog dog2 = (Dog) dog;
System.out.println(dog2.Tag);
System.out.println(dog2.sTag);
System.out.println(dog2.getSMethod());
System.out.println(dog2.getData());
System.out.println("========================");
Cat cat2 = (Cat) dog;
System.out.println(cat2.Tag);
System.out.println(cat2.sTag);
System.out.println(cat2.getSMethod());
System.out.println(cat2.getData());
}
result:
AnimalTag
SAnimalTag
SAMethod
DogData
========================
AnimalTag
SAnimalTag
SAMethod
CatData
========================
DogAnimalTag
DogSAnimalTag
DogSAMethod
DogData
========================
Exception in thread "main" java.lang.ClassCastException: com.ldx.extend.Dog cannot be cast to com.ldx.extend.Cat
at com.ldx.extend.Test.main(Test.java:30)
結論:屬性,靜态方法指向左邊,重寫的方法最終指向右邊。
3.2接口實作多态
多個類實作接口中未實作的方法,然後接口執行個體指向具體實作類的引用,調用同一函數實作不同功能。
public interface Shape {
public String zone() ;
}
public class Circle implements Shape{
@Override
public String zone() {
return "Circle";
}
}