1. 程式人生 > >面向物件——修改動物腿數(使用介面並丟擲異常)

面向物件——修改動物腿數(使用介面並丟擲異常)

 

 

需求

1.輸出各種動物叫聲

2.輸出各種動物腿數

3.實現修改引數功能

效果如下:

 

 

 實現思路

  分析:根據給出的類圖,我們可以看出有3種動物,貓、鴨子和海豚,他們都屬於父類Animal,而他們共有的特徵(屬性)在此專案有名字和叫聲(也可以定義為方法,在此專案中我定為動物的屬性),而腿數只有貓和鴨子有,海豚是沒有的,所以這個專案要求我們修改腿數只有貓和鴨子,用介面實現這個修改方法,而且輸入的腿數不正確,需要丟擲異常,且程式要正常執行。

 

  首先,根據類圖和分析,我們先寫出Animal(父類),程式碼如下:

 

package com.animal;
/**
 * 動物類
 * @author Administrator
 *
 */
public abstract class Animal {

    private String name;        //動物名字
    private String voice;       //動物叫聲
    private int leg;       //動物腿數
    
    public int getLeg() {
     return leg;
    }
    public void setLeg(int leg) {
        
this.leg = leg; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVoice() { return voice; } public void setVoice(String voice) { this.voice = voice; } public Animal(){}
//沒有腿數的帶參構造方法,給海豚初始化
public Animal(String name,String voice) { this.name=name; this.voice=voice; }
//帶腿數引數的構造方法,給貓和鴨子初始化
public Animal(String name,int leg,String voice) { this.name=name; this.leg=leg; this.voice=voice; } }

  可以看出父類的屬性有名字、叫聲、腿數,那麼海豚繼承這個父類也會有腿數屬性,但是海豚是沒有腿數的,那麼我們可以寫兩個構造方法,一個是帶腿數的構造方法,一個是不帶腿數的構造方法,我們在給海豚初始化的時候使用不帶腿數引數的構造方法就好了。

 

  父類寫完了,我們接下來寫父類的子類,貓、鴨子和海豚類!

貓類:

public class Cat extends Animal     {
    
    public Cat(){}
    public Cat(String name,int leg,String voice) {
        super(name,leg,voice);
    
    }
}

 

鴨子類:

public class Duck extends Animal {
    
    public Duck(){}
    public Duck(String name,int leg,String voice) {
        super(name,leg,voice);
        
        
    }
}

海豚類:

public class Delph extends Animal {

    public Delph(){}
    public Delph(String name,String voice) {
        super(name,voice);
    }
    
}

  現在三個子類都寫好各自的構造方法(為了方便等下初始化屬性的時候賦值);

  接下來還有一個AnimalMgr類和一個介面LuSheng,這個介面就是為了實現修改動物的資料(名字和腿數),但是在修改這個腿數之前,我們可以發現這個程式執行的時候,先輸出了一個介面,展示了動物的資訊,並且輸入0的時候,修改完寵物的資訊之後,還是會彈出這個介面,可以用do-while迴圈,那麼我們可以先寫好這個介面,也就是程式的整體的框架,修改腿數的功能稍後再寫。

  分析一下這個介面,我們可以發現,第一行只是輸出那些字而已,很簡單,System.out就可以了,但是下面展示的動物資訊,輸出了貓、鴨子、海豚的資訊,我們可以很容易就想到陣列,遍歷輸出。(不要問我為什麼很容易想到陣列,因為所以沒有道理)而用面向物件的思想來思考,這三個動物都屬於動物,那麼我們可以定義一個動物類的陣列,然後把貓、鴨子、海豚都放到這個動物數組裡面,然後給他們賦值遍歷輸出這個陣列就輸出了各個動物的資訊了。

  那麼接下來我們就在AnimalMgr類實現這個介面:  

 1 public class AnimalMgr {    
 3     Animal [] animal=new Animal[3];    //建立一個動物陣列,存放動物資訊
 4     
 5     public AnimalMgr() {
 6         animal[0]=new Cat("小貓",4,"喵喵喵");
 7         animal[1]=new Duck("小鴨",2,"嘎嘎嘎");
 8         animal[2]=new Delph("海豚","嚶嚶嚶");    
 9         Scanner input=new Scanner(System.in);
10         int type=0;
11         do {
12             System.out.println("動物名字\t腿的條數\t動物叫");
13             
14             System.out.println("是否修改資料:按0進行修改,其他數字退出");
15             type=input.nextInt();
16             if(type==0) {
17                 //進行修改操作
18             }
19         }while(type==0);
20         
21     }

  我在AnimalMgr類裡面聲明瞭一個動物陣列,重寫了一個無參建構函式,將程式的主體放入這個無參建構函式內,然後建立了三個物件,小貓、鴨子和海豚,接著用do-while迴圈實現程式的迴圈操作。我們寫一個Text類,只需要建立AnimalMgr的物件就可以了(整個main方法只有一行程式碼,就是建立AnimalMgr的物件,因為我的整個程式都在AnimalMgr類的無參構造方法AnimalMgr中),測試效果如下:

 

 

 

 

  接下來我們就需要將動物的資訊輸出,也就是存在動物數組裡的遍歷輸出,我們可以在AnimalMgr類下面寫一個方法showInfo遍歷動物陣列,輸出資訊:

  public void showInfo() {
        for (Animal animal2 : animal) {
            System.out.println(animal2.toString());
        }
    }
    

  forech遍歷輸出,再使用Object類的toString方法,但是這時候輸出的是陣列物件的地址,那麼我們可以重寫一下toSting方法,我們可以在Animal類下重寫:

package com.animal;
/**
 * 動物類
 * @author Administrator
 *
 */
public abstract class Animal {

    private String name;        //動物名字
    private String voice;        //動物叫聲
    private int leg;            //動物腿數
    
    public int getLeg() {
        return leg;
    }
    public void setLeg(int leg) {
        this.leg = leg;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getVoice() {
        return voice;
    }
    public void setVoice(String voice) {
        this.voice = voice;
    }
    public Animal(){}
    public Animal(String name,String voice) {
        this.name=name;
        this.voice=voice;
    }
    
    public Animal(String name,int leg,String voice) {
        this.name=name;
        this.leg=leg;
        this.voice=voice;
    }
    
    /**
     * 重寫toString方法
     */
    public String toString() {
        return this.name+"\t"+this.leg+"\t"+this.voice;
    }
}

  

   這時候我們再次測試,會發現,海豚也輸出了腿數,為0,這是因為我們重寫的toString方法中,return有返回leg這個引數,即使海豚的構造方法和賦值都沒有給這個引數,但是程式會預設給一個0,這時候我們可以在海豚類中再次重寫toString方法:

public class Delph extends Animal {

    public Delph(){}
    public Delph(String name,String voice) {
        super(name,voice);
    }
    

    /**
     * 重寫海豚toString方法
     */
public String toString() {    
        return this.getName()+"\t\t"+this.getVoice();
    }
}

再次執行程式:

  可以看到現在我們程式的介面和執行已經符合了需求,那麼下一步,我們要做的就是修改腿數的操作了,對於修改腿數這個操作我們是通過LuSheng介面來實現的,而且只有小貓和小鴨可以修改,所以我們要在Cat類和Duck類中實現這個介面,而需求中,當貓輸入的腿數不符合4的時候,鴨子不符合2的時候丟擲異常,且輸出程式介面(即程式異常,程式仍然會繼續執行),所以我們先建立一個介面類LuSheng:

package com.animal;
/**
 * 用於修改動物腿數的介面
 */
public interface LuSheng {
    void chang ()throws Exception;
}

  在這個介面中寫了一個chang()方法,且這個方法丟擲了一個異常,因為這個介面的實現類Cat和Duck類中實現這個介面的方法chang()也需要丟擲異常,會拋給這個介面,所以這個介面中的chang()方法也需要繼續往上拋異常。

  我們先寫Cat類的修改方法(為了方便,我將修改名字的方法也寫在了chang()方法中):

package com.animal;

import java.util.Scanner;

public class Cat extends Animal implements LuSheng {
    
    public Cat(){}
    public Cat(String name,int leg,String voice) {
        super(name,leg,voice);
    
    }

    /**
     * 實現LuSheng介面chang方法,修改貓腿數,輸入錯誤,丟擲異常
     */
    public void chang() throws Exception {     //實現介面方法丟擲異常,關鍵字thorws
        Scanner input=new Scanner(System.in);
        System.out.println("請輸入貓的名字:");
        String name=input.next();
        this.setName(name);              //將輸入的名字通過Set方法修改父類name屬性,修改名字
        System.out.println("請輸入貓的腿數:");
        int leg=input.nextInt();
        if(leg!=4) {            
            throw new Exception("貓的腿數為4!");  //當輸入的腿數不為4的是和,方法體中丟擲一個異常資訊  throw
        }else {
            this.setLeg(leg);             //輸入的是4的話就將4修改父類中的leg
        }
    }

    
    
}

 

Duck類:

package com.animal;

import java.util.Scanner;

public class Duck extends Animal implements LuSheng{
    
    public Duck(){}
    public Duck(String name,int leg,String voice) {
        super(name,leg,voice);
    }
    /**
     * 實現LuSheng介面chang方法,修改鴨子腿數,輸入錯誤,丟擲異常
     */
    public void chang() throws Exception{
        Scanner input=new Scanner(System.in);
        System.out.println("請輸入鴨的名字:");
        String name=input.next();
        this.setName(name);
        System.out.println("請輸入鴨的腿數:");
        int leg=input.nextInt();
        if(leg!=2) {
            throw new Exception("鴨的腿數為2!");
        }else {
            this.setLeg(leg);
        }    
    }    
}

Delph類(只需要修改名字,不需要實現介面,所以寫一個方法修改名字就好了,也叫chang()):

package com.animal;

import java.util.Scanner;

public class Delph extends Animal {

    public Delph(){}
    public Delph(String name,String voice) {
        super(name,voice);
    }
    //修改海豚名字的方法:
    public void chang() {
        Scanner input=new Scanner(System.in);
        System.out.println("請輸入海豚的名字:");
        String name=input.next();
        this.setName(name);
    }
    /**
     * 重寫海豚toString方法
     */
public String toString() {    
        return this.getName()+"\t\t"+this.getVoice();
    }
}

  修改的方法已經寫完了,我們只需要在type==0的判斷操作後面進行呼叫這些修改方法就可以了,按照程式的順序,首先是貓,然後是鴨子,最後是海豚,而我們在建立這個動物陣列的時候,是運用了子類指向父類的資料型別建立的物件,也就是多型的實現,但是chang()方法是各個子類獨有的,指向父類的資料型別是調用不了子類獨有的方法的,所以我們可以遍歷這個陣列,當這個資料型別是貓的時候,我們強制向下轉型,就可以呼叫子類的方法了,整個AnimalMgr程式碼如下:

package com.animal;


import java.util.Scanner;

public class AnimalMgr {
    //建立物件陣列
    Animal [] animal=new Animal[3];
    
    public AnimalMgr() {
        animal[0]=new Cat("小貓",4,"喵喵喵");            //建立貓物件,放進動物陣列animal[0]中
        animal[1]=new Duck("小鴨",2,"嘎嘎嘎");            //建立鴨子物件,放進動物陣列animal[1]中
        animal[2]=new Delph("海豚","嚶嚶嚶");            //建立海豚物件,放進動物陣列animal[2]中
        Scanner input=new Scanner(System.in);
        int type=0;
        do {
            System.out.println("動物名字\t腿的條數\t動物叫");
            showInfo();
            System.out.println("是否修改資料:按0進行修改,其他數字退出");
            type=input.nextInt();
            if(type==0) {
                for (Animal animal2 : animal) {            //遍歷陣列
                    if(animal2 instanceof Cat) {        //當前物件為貓類的時候,強制向下轉型
                        try {
                            ((Cat) animal2).chang();    //呼叫Cat類的chang()方法,且捕抓異常,輸出異常資訊之後調出迴圈
                        } catch (Exception e) {
                            e.printStackTrace();
                            break;
                        }    
                    }else if(animal2 instanceof Duck) {        //當前物件為鴨子類的時候,強制向下轉型
                        try {
                            ((Duck) animal2).chang();    //呼叫Duck類的chang()方法,且捕抓異常,輸出異常資訊之後調出迴圈
                        } catch (Exception e) {
                            e.printStackTrace();      
                            break;
                        }    
                    }else {
                        ((Delph)animal2).chang();
                    }
                    
                }
                
            }
        }while(type==0);
        
    }

    /**
     * 展示動物資訊
     */
    public void showInfo() {
        for (Animal animal2 : animal) {
            System.out.println(animal2.toString());
        }
    }
    
    
}

  當我們在呼叫各個類的實現介面的方法chang()方法的時候,我們可以用try-catch處理異常,且catch處理完異常之後,break退出forech迴圈,返回主介面,最終實現效果:

 

 

 

總結

  程式是比較簡單,但是綜合性其實比較強,物件陣列,介面,異常,重寫,當然實現的方法有很多,比如如果將叫聲定義為父類的抽象方法,各個子類再去重寫實現,遍歷的時候在呼叫這個類的叫聲的方法就可以。還有將腿數leg弄為Cat和Duck的私有屬性,在通過介面進行傳參設定,但是我個人覺得leg屬性放在父類Animal中更符合現實邏輯,這就是我面向物件的修改動物腿數(使用介面並丟擲異常)的全部思路。