對象的多態(tài)性
class 動物
{}
class 貓 extends 動物
{}
貓 x=new 貓();
動物 x=new 貓();一個對象,兩種形態(tài)。
貓這類事物既具備貓的形態(tài),又具備著動物的形態(tài)。這就是對象的多態(tài)性。
簡單說:就是一個對象對應(yīng)著不同類型
多態(tài)在代碼中的體現(xiàn)
多態(tài)的好處:
提高了代碼的擴展性,前期定義的代碼可以使用后期的內(nèi)容。
abstract class Animal {
abstract void eat();
}
class Dog extends Animal{
void eat(){
System.out.println("啃骨頭");
}
void lookHome(){
System.out.println("看家");
}
}
class Cat extends Animal{
void eat(){
System.out.println("吃魚");
}
void catchMouse(){
System.out.println("抓老鼠");
}
}
public class DuoTai {
public static void main(String[] args) {
Cat c=new Cat();
Dog d = new Dog();
// c.eat();
method(c);
method(d);
method(new Pig());
}
/*
public static void method(Cat c){
c.eat();
}
public static void method(Dog d){
d.eat();
}
*/
public static void method (Animal a){//Animal a=new Cat()(或者new Dog()),這就是多態(tài)的使用
a.eat();
}
}
//后期的內(nèi)容
class Pig extends Animal{
void eat(){
System.out.println("飼料");
}
void catchMouse(){
System.out.println("拱白菜");
}
}
運行:
多態(tài)的弊端:
前期定義的內(nèi)容不能使用(調(diào)用)后期子類特有的內(nèi)容。
public static void method (Animal a){//Animal a=new Cat()(或者new Dog()),這就是多態(tài)的使用
a.eat();
a.catchMouse();
}
運行出錯?。?!
使用多態(tài)的前提:
1 必須有關(guān)系,繼承,實現(xiàn)。
2 要有覆蓋
轉(zhuǎn)型:
public static void main(String[] args) {
Animal a=new Dog();//自動類型提升,狗對象提升為動物類型。但是特有功能無法訪問。
//作用就是限制對特有功能的訪問。
//專業(yè)講:向上轉(zhuǎn)型。
a.eat()
//如果還想用具體動物貓的特有功能。
//你還可以將該對象進(jìn)行向下轉(zhuǎn)型。
Dog d=(Dog) a;//向下轉(zhuǎn)型是為了使用子類中的特有方法。
d.eat();
d.lookHome();
//注意:對于轉(zhuǎn)型,自始自終都是子類對象在做著變化
/*
Animal a1 =new Dog();
Cat c1=(Cat) a1; 這樣轉(zhuǎn)型是不行的,運行出錯
*/
/*
Animal a =new Animal();
Cat c=(Cat) a; ClassCastException類型轉(zhuǎn)換異常
*/
}
運行:
類型判斷:instanceof
用于判斷對象的具體類型,且只能用于引用數(shù)據(jù)類型判斷
為了增強代碼的健壯性
public class DuoTai {
public static void method (Animal a){//Animal a=new Cat()(或者new Dog()),也就是說接受的可能是cat或者dog
a.eat();
Cat c= (Cat) a;
c.catchMouse();
}
public static void main(String[] args) {
method(new Cat());//可以運行
method(new Dog());//出錯:ClassCastException
}
}
這時引入關(guān)鍵字instanceof,將method方法改為:
public static void method (Animal a){
if(a instanceof Cat){//instanceof用于判斷對象的具體類型
//通常在向下轉(zhuǎn)型前用于健壯性的判斷
Cat c= (Cat) a;
c.catchMouse();
}else if(a instanceof Dog){
Dog d=(Dog) a;
d.lookHome();
}
}
調(diào)用:
public static void main(String[] args) {
method(new Cat());//可以運行
method(new Dog());//出錯:ClassCastException
}
運行:
多態(tài)時,成員的特點:
1 成員變量:
編譯時:參考引用型變量所屬的類中的是否有調(diào)用的成員變量,有,編譯通過;沒有,編譯失敗。
運行時:參考引用型變量所屬的類中的是否有調(diào)用的成員變量,并運行該所屬類中的成員變量。
簡單說,編譯和運行都參考等號的左邊。(Fu f=new Zi(); Zi z=new Zi();都參考左邊的類)
2 成員函數(shù)(非靜態(tài)):
編譯時:參考引用型變量所屬的類中的是否有調(diào)用的成員變量,有,編譯通過;沒有,編譯失敗。
運行時:參考的是對象所屬的類中是否有調(diào)用的函數(shù)
簡單說:編譯看左邊,運行看右邊
3 靜態(tài)函數(shù):
編譯時:參考引用型變量所屬的類中的是否有調(diào)用的靜態(tài)方法
運行時:參考引用型變量所屬的類中的是否有調(diào)用的靜態(tài)方法
簡單說,編譯和運行都看左邊。
其實對于靜態(tài)方法,是不需要對象的。直接用類名調(diào)用
class Fu{
int num =3;
void show(){
System.out.println("Fu");
}
static void method(){
System.out.println("Fu static");
}
}
class Zi extends Fu{// 這種繼承模式開發(fā)中基本不出現(xiàn),可能會面試
int num=4;
void show(){
System.out.println("Zi");
}
static void method(){
System.out.println("Zi static");
}
}
public class DuotaiDemo {
public static void main(String[] args) {
Zi z=new Zi();
System.out.println(z.num);
//運行結(jié)果為 4
Fu f=new Zi();
System.out.println(f.num);
//運行結(jié)果為 3
f.show();//動態(tài)綁定到指定的對象上
//運行結(jié)果為Zi,
//若把Fu類中的show方法注釋掉,則運行出錯
//若把Zi類中的show方法注釋掉,則運行結(jié)果為Fu
f.method();
//運行結(jié)果為Fu static 靜態(tài)調(diào)用不需要創(chuàng)建對象
}
}
運行: