什麼是多態
多態,顧名思義,就是多種形態;是同一個行爲具有多個不同表現形式或形態的能力。如學生是人的一種,則一個具體的同學小明既是學生也是人,即出現兩種形態
多態的體現格式
父類名稱 變量名 = new 子類對象;
接口名稱 對象名 = new 實現類名稱();
多態存在的三個必要條件
多態的前提是類與類之間存在關係,要麼繼承、要麼實現或方法存在覆蓋
1、繼承:多態中必須存在有繼承關係的子類和父類
2、重寫:子類對父類中某些方法進行重新定義,在調用這些方法時就會調用子類的方法
3、父類引用指向子類對象(向上轉型):多態中需要將子類的引用賦給父類對象,只有這樣該引用才能夠具備技能調用父類的方法和子類的方法
例子
基於繼承實現的多態
class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Animal(){
}
public void breathe(){
System.out.println("呼吸");
}
/**
* 重寫Object類toString()
*/
public String toString(){
return null;
}
}
class Rabbit extends Animal{
public Rabbit(){
setName("兔子");
}
/**
* 重寫父類方法,實現多態
*/
public void breathe(){
System.out.println(getName()+"呼吸");
}
public String toString(){
return "Animal:" + getName();
}
}
class Cat extends Animal{
public Cat(){
setName("Cat");
}
/**
* 重寫父類方法,實現多態
*/
public void breathe(){
System.out.println(getName()+"呼吸");
}
public String toString(){
return "Animal:" + getName();
}
}
public class Test {
public static void main(String[] args) {
Animal rabbit = new Rabbit();
Animal cat = new Cat();
rabbit.breathe();
cat.breathe();
Rabbit rabbit1 = new Rabbit();
Cat cat1 = new Cat();
rabbit1.breathe();
cat1.breathe();
}
}
基於接口實現的多態
interface Animal {
public void eat();
public void activity();
}
class Rabbit implements Animal{
@Override
public void eat() {
System.out.println("喫草");
}
@Override
public void activity() {
System.out.println("跳");
}
public static void main(String[] args) {
Animal animal = new Rabbit();
animal.eat();
animal.activity();
Rabbit rabbit = new Rabbit();
rabbit.eat();
rabbit.activity();
}
}
多態中成員的特點
引用變量在編譯階段只能調用編譯時類型所具有的方法,但運行時則執行他運行時類型所具有的方法
class Animal{
public int month = 1;
public void eat(){
System.out.println("喫東西");
}
}
class Dog extends Animal{
public int month = 2;
public void eat() {
System.out.println("小狗喫肉");
}
public void sleep() {
System.out.println("小狗睡覺");
}
}
class Cat extends Animal{
public int month = 3;
public void eat() {
System.out.println("小貓喫魚");
}
}
public class Test {
public static void main(String[] args){
Animal a = new Dog();
Animal b = new Cat();
a.eat();
System.out.println(a.month);
//下面代碼編譯時會出錯
//a.sleep();
b.eat();
System.out.println(b.month);
}
}
多態中成員函數的特點
在編譯時期,參考引用型變量所屬的類中是否有調用方法,如果有,編譯通過,否則編譯失敗
在運行時期,參考對象所屬的類中是否有調用的方法
也就是編譯看左邊,運行看右邊
多態中成員變量的特點
編譯和運行都參考左邊(引用型變量所屬的類)
多態中靜態成員函數的特點
編譯和運行都參考左邊
多態中引用類型轉換
向上轉型: 多態本身就是向上轉型過的過程
使用格式:父類類型 變量名=new 子類類型();
適用場景:當不需要面對子類類型時,通過提高擴展性,或者使用父類的功能就能完成相應的操作Animal animal = new Dog();
向下轉型: 父類類型向子類類型向下轉換的過程,這個過程是強制的。 一個已經向上轉型的子類對象,將父類引用轉爲子類引用,可以使用強制類型轉換的格式,便是向下轉型
使用格式:子類類型 變量名 = (子類類型) 父類變量名;
含義:將父類對象還原成爲本來的子類對象Dog dog = (Dog) animal;
注意:
必須保證對象創建的時候就是轉型後的對象,才能向下轉型。否則運行時,報出了 ClassCastException(類型轉換異常)
多態的優點與弊端
優點
1、消除類型之間的耦合關係
2、可替換性
3、可擴充性
4、接口性
5、靈活性
6、簡化性
弊端
只能使用父類的引用訪問父類中的成員