JAVA利用接口實現(xiàn)多繼承問題的代碼實操演示
hello,上文帶大家學習了java中類的繼承,我們可以創(chuàng)建一個父類,將類中的共性抽取出來,通過子類繼承的方式來實現(xiàn)代碼的復用。今天帶大家學習不同類之間的另外幾種關系,即多態(tài)抽象類和接口。
多態(tài)的概念
多態(tài),從字面意思去形象的理解可以解釋為:針對不同的對象執(zhí)行某一行為時,不同的對象會有不同的狀態(tài)。
比如貓和狗都是動物,他們都有進食這個行為但是當我們調(diào)用狗這個對象時,吃的是狗糧,而調(diào)用貓時,則會選擇吃貓食。
代碼實操演示
class Animal{
String name;
int age;
public Animal(String name,int age){
this.name=name;
this.age=age;
}
public void eat(){
System.out.println("正在吃飯");
}
}
class Cat extends Animal{
public Cat(String name, int age) {
super(name, age);//調(diào)用父類的構(gòu)造方法
}
@Override
public void eat() {
System.out.println(this.name+"正在吃貓食");;
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃狗糧");
}
}
public class Test {
public static void eat(Animal a){
a.eat();//這里放的是父類具體引用的是誰看傳的對象
}
public static void main(String[] args) {
Cat cat=new Cat("寶寶",3);
Dog dog=new Dog("旺財",3);
eat(dog);//傳的狗
eat(cat);//傳的貓,這里其實就是動態(tài)綁定
}
}
這里還是解釋一下,我們通過子類方法對父類的重寫,后面又在Test類里創(chuàng)建eat()這里傳的是Animal類,由于Animal是Dog和Cat的父類,所以后面我們在調(diào)用eat()時可以傳Dog和Cat形,即小范圍包含于大范圍。這就是多態(tài)的含義。
類中方法的重寫:
重寫:又稱覆蓋,子類可以對父類中的非靜態(tài),非private,非final,非構(gòu)造方法的其他方法進行重新定義,注意:重寫的方法返回值不能改變,方法的參數(shù)不能改變,方法名也不能改變。即方法的外殼,不變只對里面進行重新編寫。我們可以根據(jù)子類的需要對父類中的方法進行重新定義。通常重寫的方法會有一個標簽 @override,上面的程序里有提及。
這里可以對比記憶一下我們學過的重載:

注意:重寫是對于子類和父類中研究的,即不同類之間,而重載是在一個類中實現(xiàn)了多個參數(shù)不同的同名的方法。
動態(tài)綁定:即不能立馬確定方法的行為,編譯時不能確定,等到運行時才能世道方法到底調(diào)用的是哪個方法的類。
父類當中的向下轉(zhuǎn)移和向上轉(zhuǎn)移
就是將子類引用給父類來使用,將小范圍賦值給大范圍,但本質(zhì)上仍然為子類對象。

所以運行的結(jié)果為寶寶吃貓食。

當然你也可以使用Dog類來進行向下轉(zhuǎn)型,因為Animal也包含Dog。
直接賦值
方法的返回值
方法的參數(shù)
直接賦值:
Animal animal=new Cat("寶寶",10);
當做返回值:


向上轉(zhuǎn)型的優(yōu)點:代碼更加靈活。
向上轉(zhuǎn)型的缺點:無法調(diào)用子類中的特有方法。
那如果我們就是要調(diào)用子類中的特有方法怎么辦呢?這就需要使用向下轉(zhuǎn)型了。
向下轉(zhuǎn)型:

我們可以使用關鍵字instanceof來對向下轉(zhuǎn)型的對象做一層檢驗,保障了代碼的安全性。
if(animal instanceof Cat){
cat=(Cat)animal;
cat.mew();這里只有animal引用了Cat類的對象才執(zhí)行if語句。
多態(tài)的優(yōu)點
那么多態(tài)到底有什么優(yōu)點呢,這里給大家總結(jié)一下,多態(tài)可以降低代碼的圈復雜度,可以避免使用過多的if-else語句,其次,可拓展能力強需要新增一個類時,直接繼承就好,需要注意構(gòu)造方法么有多態(tài)性。
class B {
public B() {
// do nothing
func();
}
public void func() {
System.out.println("B.func()");
}
}
class D extends B {
private int num = 1;
@Override
public void func() {
System.out.println("D.func() " + num);
}
}
public class Test {
public static void main(String[] args) {
D d = new D();
}
}
// 執(zhí)行結(jié)果
D.func() 0這里給大家一段有意思的代碼,運行結(jié)果你猜對了嗎,原因是new() D之后,第一步應該是調(diào)用父類的構(gòu)造方法,即func(),但是構(gòu)造方法在子類中被重寫,所以調(diào)用的是子類中的func(),此時子類中的成員變量還沒有賦值所以num仍然為0,所以運行結(jié)果為D.func() 0
抽象類即抽象方法的重寫
其實,我們在最上面的代碼中發(fā)現(xiàn)了一個問題,很多類由于不能將一個事物準確描述出來,針對不同的事物的行為不同,執(zhí)行的方法也應該不同,比如Animal中的eat()并不能準確描述狗吃的狗糧,貓吃的貓糧,我們在狗類和貓類中還是要重寫這個eat()方法,類似與Animal的這些類可以理解為抽象類。
抽象類,修飾限定符為public abstract,抽象類中的抽象方法(修飾符也是public abstract)類似與eat(),是不能有具體的定義的,原因很好理解,即使你寫了,每個子類還得重寫這個方法,我們只聲明這個方法即可。注意:有抽象方法的類一定是抽象類,抽象類不一定含有抽象方法,抽象類也是類可以定義普通的成員變量,方法甚至是構(gòu)造方法。(非常重要!?。?!)
上代碼理解一下:
//抽象類
public Abstract Animal{
public abstract void eat();//抽象方法
public abstract void look();//抽象方法
}抽象類也不能實例化對象,因為抽像類無法完整描述一個事物,他只能被子類繼承,然后子類必須將抽象類當中的抽象方法進行重寫,否則編譯報錯,
抽象方法不能是 private 的,因為子類還要重寫抽象方法的。
抽象方法不能被final和static修飾,因為抽象方法要被子類重寫 。
接口的概念:
說到接口,我們第一想到的應該是USB接口插座...,這些當然都算接口,那么讓我來說接口的特性的話,我覺得接口首先是一個封裝好了的東西,并且它有著自己的功能,如果某個東西有了接口,那么他也應該具有接口的特性。

在java中接口是多個類的公共規(guī)范,是一種引用數(shù)據(jù)類型,接口的定義格式與定義類的格式基本相同,將class關鍵字換成 interface 關鍵字,就定義了一個接口。
interface A{
public abstract void method1(); // public abstract 是固定搭配,可以不寫
public void method2();
abstract void method3()
}接口不能直接使用,必須要有一個"實現(xiàn)類"來"實現(xiàn)"該接口,實現(xiàn)接口中的所有抽象方法。 這也比較好理解,畢竟接口只是實現(xiàn) 了某個特定的功能,并不能描述一個具體的對象。我們使用關鍵字implement將類和接口連接起來。
public class Animal implements IRunning{
// ...
}這里給大家舉一個電腦的例子:
// USB接口
public interface USB {
void openDevice();
void closeDevice();
}// 鼠標類,實現(xiàn)USB接口
public class Mouse implements USB {
@Override
public void openDevice() {
System.out.println("打開鼠標");
}
@Override
public void closeDevice() {
System.out.println("關閉鼠標");
}
public void click(){
System.out.println("鼠標點擊");
}
}// 鍵盤類,實現(xiàn)USB接口
public class KeyBoard implements USB {
@Override
public void openDevice() {
System.out.println("打開鍵盤");
}
@Override
public void closeDevice() {
System.out.println("關閉鍵盤");
}
public void inPut(){
System.out.println("鍵盤輸入");
}
}// 筆記本類:使用USB設備
public class Computer {
public void powerOn(){
System.out.println("打開筆記本電腦");
}
public void powerOff(){
System.out.println("關閉筆記本電腦");
}public void useDevice(USB usb){
usb.openDevice();
if(usb instanceof Mouse){
Mouse mouse = (Mouse)usb;
mouse.click();
}else if(usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard)usb;
keyBoard.inPut();
}
usb.closeDevice();
}
}// 測試類:
public class TestUSB {
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();
// 使用鼠標設備
computer.useDevice(new Mouse());
// 使用鍵盤設備
computer.useDevice(new KeyBoard());
computer.powerOff();
}
}接口雖然是一種引用類型但是,他不能new(),必需通過引用類來重寫接口中的所有方法,并且每個方法都默認為public abstract,也可以使用static和default修飾但是必須立即定義該方法,注意重寫方法時一定要用public修飾。
public interface USB {
void openDevice(); // 默認是public的
void closeDevice(); // 默認是public的
}
public class Mouse implements USB {
@Override
void openDevice() {
System.out.println("打開鼠標");
}
// ...
}
// 編譯報錯,重寫USB中openDevice方法時,不能使用默認修飾符
// 正在嘗試分配更低的訪問權限; 以前為public而且一個類是可以實現(xiàn)多個接口的,這也間接解決了java的多繼承問題。
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}interface IFlying {
void fly();
}
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}class Cat extends Animal implements IRunning {
public Cat(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.name + "正在用四條腿跑");
}
}class Fish extends Animal implements ISwimming {
public Fish(String name) {
super(name);
}
@Override
public void swim() {
System.out.println(this.name + "正在用尾巴游泳");
}
}總結(jié)
到此這篇關于JAVA利用接口實現(xiàn)多繼承問題的文章就介紹到這了,更多相關JAVA用接口實現(xiàn)多繼承內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot 設置CorsFilter跨域不生效的解決
這篇文章主要介紹了springboot 設置CorsFilter跨域不生效的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
教你用java完美封裝微信模板消息的發(fā)送動態(tài)
這篇文章主要介紹了教你用java完美封裝微信模板消息的發(fā)送動態(tài),文中有非常詳細的代碼示例,對正在學習java的小伙伴們有很好的幫助,需要的朋友可以參考下2021-04-04
SpringBoot+mybatis+thymeleaf實現(xiàn)登錄功能示例
這篇文章主要介紹了SpringBoot+mybatis+thymeleaf實現(xiàn)登錄功能示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07
java面向?qū)ο缶幊讨匾拍罾^承和多態(tài)示例解析
這篇文章主要為大家介紹了java面向?qū)ο缶幊痰膬蓚€重要概念繼承和多態(tài)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
spring Profile如何為不同環(huán)境提供不同的配置支持
這篇文章主要介紹了spring Profile如何為不同環(huán)境提供不同的配置支持,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-08-08

