對象的多態(tài)性
class 動(dòng)物
{}
class 貓 extends 動(dòng)物
{}
貓 x=new 貓();
動(dòng)物 x=new 貓();一個(gè)對象,兩種形態(tài)墓怀。
貓這類事物既具備貓的形態(tài)汽纠,又具備著動(dòng)物的形態(tài)。這就是對象的多態(tài)性傀履。
簡單說:就是一個(gè)對象對應(yīng)著不同類型
多態(tài)在代碼中的體現(xiàn)
多態(tài)的好處:
提高了代碼的擴(kuò)展性虱朵,前期定義的代碼可以使用后期的內(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("拱白菜");
}
}
運(yùn)行:多態(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();
}
運(yùn)行出錯(cuò)0鹉骸7!
使用多態(tài)的前提:
1 必須有關(guān)系啦粹,繼承偿荷,實(shí)現(xiàn)窘游。
2 要有覆蓋
轉(zhuǎn)型:
public static void main(String[] args) {
Animal a=new Dog();//自動(dòng)類型提升,狗對象提升為動(dòng)物類型跳纳。但是特有功能無法訪問删顶。
//作用就是限制對特有功能的訪問伊约。
//專業(yè)講:向上轉(zhuǎn)型。
a.eat()
//如果還想用具體動(dòng)物貓的特有功能。
//你還可以將該對象進(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)型是不行的蛾魄,運(yùn)行出錯(cuò)
*/
/*
Animal a =new Animal();
Cat c=(Cat) a; ClassCastException類型轉(zhuǎn)換異常
*/
}
運(yùn)行:類型判斷:instanceof
用于判斷對象的具體類型,且只能用于引用數(shù)據(jù)類型判斷
為了增強(qiáng)代碼的健壯性
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());//可以運(yùn)行
method(new Dog());//出錯(cuò):ClassCastException
}
}
這時(shí)引入關(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());//可以運(yùn)行
method(new Dog());//出錯(cuò):ClassCastException
}
運(yùn)行:多態(tài)時(shí)逛拱,成員的特點(diǎn):
1 成員變量:
編譯時(shí):參考引用型變量所屬的類中的是否有調(diào)用的成員變量敌厘,有,編譯通過朽合;沒有俱两,編譯失敗。
運(yùn)行時(shí):參考引用型變量所屬的類中的是否有調(diào)用的成員變量曹步,并運(yùn)行該所屬類中的成員變量宪彩。
簡單說,編譯和運(yùn)行都參考等號(hào)的左邊讲婚。(Fu f=new Zi(); Zi z=new Zi();都參考左邊的類)
2 成員函數(shù)(非靜態(tài)):
編譯時(shí):參考引用型變量所屬的類中的是否有調(diào)用的成員變量尿孔,有,編譯通過筹麸;沒有活合,編譯失敗。
運(yùn)行時(shí):參考的是對象所屬的類中是否有調(diào)用的函數(shù)
簡單說:編譯看左邊物赶,運(yùn)行看右邊
3 靜態(tài)函數(shù):
編譯時(shí):參考引用型變量所屬的類中的是否有調(diào)用的靜態(tài)方法
運(yùn)行時(shí):參考引用型變量所屬的類中的是否有調(diào)用的靜態(tài)方法
簡單說白指,編譯和運(yùn)行都看左邊。
其實(shí)對于靜態(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),可能會(huì)面試
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);
//運(yùn)行結(jié)果為 4
Fu f=new Zi();
System.out.println(f.num);
//運(yùn)行結(jié)果為 3
f.show();//動(dòng)態(tài)綁定到指定的對象上
//運(yùn)行結(jié)果為Zi奖地,
//若把Fu類中的show方法注釋掉状蜗,則運(yùn)行出錯(cuò)
//若把Zi類中的show方法注釋掉,則運(yùn)行結(jié)果為Fu
f.method();
//運(yùn)行結(jié)果為Fu static 靜態(tài)調(diào)用不需要?jiǎng)?chuàng)建對象
}
}
運(yùn)行: