一臀叙、方法重寫(override)
在子類中將父類的方法再重新定義一遍稱之為方法重寫
-
什么時候需要方法重寫:
- 如果父類繼承的方法不能滿足子類的需要,或者不適合子類的需要劝萤。此時子類可以從父類繼承的方法重寫定義為滿足自己需要的方法渊涝。
在下例中,Cat類繼承了Pet的sound方法床嫌,但是并不適用于cat驶赏,此時可以進(jìn)行方法的重寫。
public class Pet {
private int weight ;
private String color;
//方法sound
public void sound(){
}
}
public class Cat extends Pet {
@Override//方法重寫既鞠,實(shí)現(xiàn)貓叫
public void sound() {
System.out.println("喵喵喵");
}
}
再創(chuàng)建一個Dog類,讓Dog類也繼承Pet類盖文,并且也進(jìn)行方法重寫嘱蛋,實(shí)現(xiàn)狗的叫聲
public class Dog extends Pet{
@Override
public void sound(){
System.out.println("汪汪汪");
}
}
在main方法中創(chuàng)建對象,調(diào)用sound方法五续,輸出cat和dog的叫聲
public class PetShop{//寵物店
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound();//調(diào)用狗的sound()
Cat cat = new Cat();
cat.sound();//調(diào)用貓的sound()
}
}
使用方法重寫的注意事項(xiàng):
- 在方法重寫時洒敏,方法的返回值、方法名疙驾、參數(shù)都要和父類一樣凶伙,否則就算不是方法重寫了,而是cat類新定義的方法它碎。
- 子類方法覆蓋父類方法函荣,必須要保證子類訪問權(quán)限大于父類訪問權(quán)限
public void sound(){
}//Pet類中為public
而在子類中,訪問權(quán)限為private扳肛,訪問權(quán)限低于父類而報錯
public class Dog extends Pet{
@Override
private void sound(){//private處報錯
System.out.println("汪汪汪");
}
}
- 重寫的方法所拋出的異常必須和被重寫方法的所拋出的異常一致傻挂,或者是其子類
二、里氏替換原則
里氏替換原則(父類引用指向子類實(shí)例)
- 里氏替換原則主要闡述了有關(guān)繼承的一些原則挖息,也就是什么時候應(yīng)該使用繼承金拒,什么時候不應(yīng)該使用繼承套腹,以及其中蘊(yùn)含的原理。里氏替換原是繼承復(fù)用的基礎(chǔ)笤休,它反映了基類與子類之間的關(guān)系蛤育,是對開閉原則的補(bǔ)充瓦糕,是對實(shí)現(xiàn)抽象化的具體步驟的規(guī)范咕娄。
- 簡單的理解為一個軟件實(shí)體如果使用的是一個父類,那么一定適用于其子類费变,而且它察覺不出父類對象和子類對象的區(qū)別。也就是說吁峻,軟件里面,把父類都替換成它的子類矮慕,程序的行為沒有變化痴鳄。如果軟件開發(fā)中使用的是其子類的話痪寻,由于子類含有一些父類所沒有的特征槽华,所以父類不能代替其子類。相反,子類一定含有父類的公開的方法勇凭,那么子類一定可以代替父類虾标,也就是使用父類的地方都可以使用子類
在上邊的例子中璧函,我們每次都是創(chuàng)建了cat或者dog對象來調(diào)用sound方法蘸吓,是指定了貓叫還是狗叫库继。那么如果要求的是一只pet來叫呢?
public class Test {
public static void main(String[] args) {
Pet pet = new Dog();
pet.sound();//pet調(diào)用Dog中sound方法
pet = new Cat();
pet.sound();//pet調(diào)用Cat中sound方法
}
}
在例子中拜英,將父類Pet的引用指向了子類的實(shí)例琅催,通過pet調(diào)用sound方法,將子類替代了父類狰右。
父類引用指向子類對象的結(jié)論:
- 父類引用可以代表任何其子類對象棋蚌,代碼表現(xiàn)為
Pet pet = new Dog()
或者Pet pet = new Cat()
- 父類引用指向哪個子類對象谷暮,調(diào)用的方法就是哪個子類中的方法。
- 父類引用指向子類對象其實(shí)是增強(qiáng)了父類的功能瓤漏。
由于子類含有一些父類所沒有的特征蝶俱,所以父類不能代替其子類
例如
public void climb(){
System.out.println("貓貓爬樹中榨呆。积蜻。竿拆。");
}//Cat類新增的方法
在Cat類中新增了父類沒有的climb()方法
pet = new Cat();
pet.sound();
pet.climb();//climb處報錯
代碼報錯了,為什么呢央勒?
因?yàn)楦割愐谜{(diào)用方法時稳吮,必須知道子類有哪些方法灶似,知道的才能調(diào)用酪惭,不知道的是不能調(diào)用的。
子類Cat新增的climb()方法父類并不知道鲫懒,但是父類一定知道子類從父類繼承的方法窥岩。
所以父類引用只能調(diào)用子類與父類保持繼承關(guān)系的方法颂翼【卫穑可以是重寫的方法集歇。
里氏替換中的調(diào)用規(guī)則
- 父類引用只能調(diào)用子類從父類繼承的方法际歼。
- 當(dāng)子類重寫父類方法后鹅心,父類引用調(diào)用的是子類重寫的方法,否則調(diào)用子類從父類繼承的方法输枯。