為了賬號安全,請及時綁定郵箱和手機立即綁定

來談談JAVA面向對象 - 魯班即將五殺,大喬送他回家??

2018.03.12 21:12 5857瀏覽

開發IDE為Eclipse或者MyEclipse。

首先,如果我們使用面向過程的思維來解決這個問題,就是第一步做什么,第二步做什么?

魯班即將五殺,大喬送他回家

這個現象可以簡單地拆分為兩步,代碼大概是這個樣子的:

public class Test01 {

    public static void main(String[] args) {
        System.out.println("魯班即將五殺");
        System.out.println("大喬送他回家");
    }

}

面向過程的思維大概就是這樣。

如果我們用面向對象的思維來看待這個問題,首先,得抽象出有哪幾個對象。

魯班類:

/**
 * 魯班類
 * @author Administrator
 *
 */
public class Luban {

    private String name = "魯班"; //英雄的名字
    private int killCount = 0;    //擊殺個數

}

因為魯班會有一個從 first bloodpenta kill 的過程 , 在這個過程中,需要對killCount 這個變量一步步遞增,所以,我們給它再加一個kill方法。

public void kill(){
    killCount++;

    switch (killCount) {
    case 1:
        System.out.println("First Blood!");
        break;
    case 2:
        System.out.println("Double Kill!");
        break;
    case 3:
        System.out.println("Triple kill!");
        break;
    case 4:
        System.out.println("Quadra kill!");
        break;
    case 5:
        System.out.println("Penta kill!");
        break;

    default:
        break;
    }

}

這個時候,我們發現,訪問不了私有變量。我們需要給name和killCount添加對應的get,set方法:

Alt + S --> Generator Getters and Setters -->

這樣就自動生成了!

至此,魯班類告一段落,接下來編寫大喬類:

/**
 * 大喬類
 * @author Administrator
 *
 */
public class Daqiao {

    private String name = "大喬";

    /**
     * 放大招的方法
     */
    public void DaZhao(Luban luban){

    }

}

大招方法需要把魯班給裝進去,大家思考如何實現送魯班回家的過程?

這邊我提供一個思路,給魯班添加一個私有的布爾屬性 isAtHome,默認是false。當魯班被傳遞進大喬的大招方法里之后,就改為true。

private boolean isAtHome = false; //是否回泉水?

別忘了生成 get set 方法。

于是乎,大招方法就變成了這樣:

/**
 * 放大招的方法
 */
public void DaZhao(Luban luban){
    luban.setAtHome(true);
}

現在大家再想一個問題,當魯班回泉水了,還能不能繼續調用 kill 方法?

肯定是不能了,修改后的 kill 方法,在killCount++之前就應該return掉:

public void kill(){

    if(this.isAtHome){
        setName("魯班七號");
        System.out.println(name + ":我是誰,在干什么??");
        return;
    }

    killCount++;

    switch (killCount) {
    case 1:
        System.out.println("First Blood!");
        break;
    case 2:
        System.out.println("Double Kill!");
        break;
    case 3:
        System.out.println("Triple kill!");
        break;
    case 4:
        System.out.println("Quadra kill!");
        break;
    case 5:
        System.out.println("Penta kill!");
        break;

    default:
        break;
    }

}

測試:

import bean.Daqiao;
import bean.Luban;

public class Test02 {

    public static void main(String[] args) {
        Luban luban = new Luban();
        luban.kill();
        luban.kill();
        luban.kill();
        luban.kill();

        Daqiao dq = new Daqiao();

        dq.DaZhao(luban);

        luban.kill();

    }
}

以上就是我們面向對象的一般思路,先抽象出有幾個類,然后設計每個類中有哪些方法?

面向對象有三大特性,分別為繼承,封裝和多態。

繼承

還是這個例子,思考:魯班和大喬都屬于王者峽谷里面的英雄。他們有很多共同的特性。我們可以抽象出一個通用的英雄類,Hero類 。

package bean;

/**
 * 英雄類
 * @author Administrator
 *
 */
public class Hero {

    protected String name;
    protected int killCount = 0;
    protected boolean isAtHome = false;

    public void kill(){

    }

    public void DaZhao(){

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getKillCount() {
        return killCount;
    }

    public void setKillCount(int killCount) {
        this.killCount = killCount;
    }

    public boolean isAtHome() {
        return isAtHome;
    }

    public void setAtHome(boolean isAtHome) {
        this.isAtHome = isAtHome;
    }

}

然后讓魯班和大喬都繼承這個類。

對魯班而言,繼承了Hero類以后,只需要重寫kill即可,省去了很多代碼:

package bean;

/**
 * 魯班類
 * @author Administrator
 *
 */
public class Luban extends Hero{

    public void kill(){

        if(this.isAtHome){
            System.out.println(name + ":我是誰,在干什么??");
            return;
        }

        killCount++;

        switch (killCount) {
        case 1:
            System.out.println("First Blood!");
            break;
        case 2:
            System.out.println("Double Kill!");
            break;
        case 3:
            System.out.println("Triple kill!");
            break;
        case 4:
            System.out.println("Quadra kill!");
            break;
        case 5:
            System.out.println("Penta kill!");
            break;

        default:
            break;
        }

    }

}

大喬類也是同樣的道理:

package bean;

/**
 * 大喬類
 * @author Administrator
 *
 */
public class Daqiao extends Hero{

    /**
     * 放大招的方法
     */
    public void DaZhao(Luban luban){
        luban.setAtHome(true);
    }

}

這個時候,我們可以看到,繼承的一個好處就是可以省去很多重復的代碼,提高了代碼的復用率。

封裝

現在我們考慮如何讓java程序來播放一個音樂?

經過改造后的魯班 kill 方法:

public void kill(){

    if(this.isAtHome){
        setName("魯班七號");
        System.out.println(name + ":我是誰,在干什么??");
        return;
    }

    killCount++;

    switch (killCount) {
    case 1:

        //解析音樂地址
        try{
            URL codebase = new URL("file:/E:/workspace/demos/1.wav");
            AudioClip a = Applet.newAudioClip(codebase);
            a.play(); //播放音樂
            Thread.sleep(2000);
        }catch(Exception e){
            System.out.println("錯就錯唄,無所謂!");
        }

        System.out.println("First Blood!");
        break;

    case 2:

        //解析音樂地址
        try{
            URL codebase = new URL("file:/E:/workspace/demos/2.wav");
            AudioClip a = Applet.newAudioClip(codebase);
            a.play(); //播放音樂
            Thread.sleep(2000);
        }catch(Exception e){
            System.out.println("錯就錯唄,無所謂!");
        }
        System.out.println("Double Kill!");
        break;
    case 3:

        //解析音樂地址
        try{
            URL codebase = new URL("file:/E:/workspace/demos/3.wav");
            AudioClip a = Applet.newAudioClip(codebase);
            a.play(); //播放音樂
            Thread.sleep(2000);
        }catch(Exception e){
            System.out.println("錯就錯唄,無所謂!");
        }

        System.out.println("Triple kill!");
        break;
    case 4:
        //解析音樂地址
        try{
            URL codebase = new URL("file:/E:/workspace/demos/4.wav");
            AudioClip a = Applet.newAudioClip(codebase);
            a.play(); //播放音樂
            Thread.sleep(2000);
        }catch(Exception e){
            System.out.println("錯就錯唄,無所謂!");
        }
        System.out.println("Quadra kill!");
        break;
    case 5:
        //解析音樂地址
        try{
            URL codebase = new URL("file:/E:/workspace/demos/5.wav");
            AudioClip a = Applet.newAudioClip(codebase);
            a.play(); //播放音樂
            Thread.sleep(2000);
        }catch(Exception e){
            System.out.println("錯就錯唄,無所謂!");
        }
        System.out.println("Penta kill!");
        break;

    default:
        break;
    }

}

從代碼中,我們可以發現,播放音樂的代碼很多都是重復的,這個時候,我們就考慮能不能單獨封裝一個類,來播放音樂。

比如,我們可以新建一個音樂工具類,下次要播放音樂的時候,就調用這個類的方法。

package util;

import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;

public class MusicUtil {

    /**
     *  音樂工具類
     * @param path 音樂地址
     * @param seconds 秒數
     */
    public static void playWav(String path,int seconds){
        try{
            URL codebase = new URL("file:/" + path);
            AudioClip a = Applet.newAudioClip(codebase);
            a.play(); //播放音樂
            Thread.sleep(seconds * 1000);
        }catch(Exception e){
            System.out.println("錯就錯唄,無所謂!");
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        MusicUtil.playWav("E:\\workspace\\demos\\luban.wav", 5);

    }

}

有了這個工具類,之前播放音樂的代碼只需要一句話便可代替:

package bean;

import util.MusicUtil;

/**
 * 魯班類
 * @author Administrator
 *
 */
public class Luban extends Hero{

    public void kill(){

        if(this.isAtHome){
            setName("魯班七號");
            System.out.println(name + ":我是誰,在干什么??");
            return;
        }

        killCount++;

        switch (killCount) {
        case 1:

            MusicUtil.playWav("E:/workspace/demos/1.wav", 2);

            System.out.println("First Blood!");
            break;

        case 2:

            MusicUtil.playWav("E:/workspace/demos/2.wav", 2);
            System.out.println("Double Kill!");
            break;
        case 3:

            MusicUtil.playWav("E:/workspace/demos/3.wav", 2);

            System.out.println("Triple kill!");
            break;
        case 4:
            MusicUtil.playWav("E:/workspace/demos/4.wav", 2);
            System.out.println("Quadra kill!");
            break;
        case 5:
            MusicUtil.playWav("E:/workspace/demos/5.wav", 2);
            System.out.println("Penta kill!");
            break;

        default:
            break;
        }

    }

    public void say(){

        MusicUtil.playWav("E:/workspace/demos/luban.wav", 5);
    }

}

甚至,這些工具類,我們還可以單獨打成一個jar包,發布到網上,供別人使用!

新建一個musicutil項目:

我們添加一個util包,把剛才的MusicUtil.java復制進來即可:

現在開始打包,右鍵項目,選擇Export,Export:


如果下次我們想要在其他項目中播放音樂的話,只需要引入這個jar即可,甚至,你要是閑得無聊的話,可以發布到網上,供別人下載使用。

回到封裝的解說,我們可以把那些經常使用的,重復率特別高的代碼,封裝成一個方法,達到代碼復用的目的。如果不封裝,可想而知,我們的類中底層代碼會特別多,不利于旁人理解,也不利于我們今后維護代碼,因為方法名是我們自己取的,所以日后也可以很好的理解當初的代碼是什么意思。

封裝的另一個好處就是,有些東西,我不會,但是別人封裝好了,我是不是可以去下載拿來用??

又比如jdk給我們封裝大部分java開發需要的類,這些類,很多都極其復雜,但是因為sun公司已經給我們封裝好了,所以我們也完全不需要去關心其底層的實現,比如String,比如HashMap,直接拿來就用,而且效率很高!

所以,我認為,封裝另一個好處就是,我不會的東西,只要有人會,就好了,我照樣可以拿來開發程序!

多態
/**
 * 大喬類
 * @author Administrator
 *
 */
public class Daqiao extends Hero{

    /**
     * 放大招的方法
     */
    public void DaZhao(Luban luban){
        luban.setAtHome(true);
        luban.say();
    }

}

回顧大喬類,問一下大家,大喬的大招對魯班有效,對蘭陵王有沒有效?對露娜有沒有效?

如果我們現在新建了一個露娜類:

package bean;

import util.MusicUtil;

/**
 * 露娜類
 * @author Administrator
 *
 */
public class Luban extends Hero{

    public void kill(){

        if(this.isAtHome){
            setName("露娜");
            System.out.println(name + ":我是誰,在干什么??");
            return;
        }

        killCount++;

        switch (killCount) {
        case 1:

            MusicUtil.playWav("E:/workspace/demos/1.wav", 2);

            System.out.println("First Blood!");
            break;

        case 2:

            MusicUtil.playWav("E:/workspace/demos/2.wav", 2);
            System.out.println("Double Kill!");
            break;
        case 3:

            MusicUtil.playWav("E:/workspace/demos/3.wav", 2);

            System.out.println("Triple kill!");
            break;
        case 4:
            MusicUtil.playWav("E:/workspace/demos/4.wav", 2);
            System.out.println("Quadra kill!");
            break;
        case 5:
            MusicUtil.playWav("E:/workspace/demos/5.wav", 2);
            System.out.println("Penta kill!");
            break;

        default:
            break;
        }

    }

    public void say(){

        MusicUtil.playWav("E:/workspace/demos/zixia.wav", 5);
    }

}

同時,在父類中,添加say方法:

public void say(){

}

這個時候,大喬的大招是無法裝進露娜類的。

測試:

對大喬來說,不管你是什么英雄,只要你繼承了Hero類,都可以分分鐘送你回家!所以,我們要改變大招方法的參數:

/**
 * 放大招的方法
 */
public void DaZhao(Hero hero){
    hero.setAtHome(true);
    hero.say();
}

這就是所謂的多態。

從這個例子當中,我們可以看出,多態最直接的好處就是某個方法中,同一個參數可以接收多種類型的數據。

比如剛才大喬的例子,如果我們不用多態,那么大招方法就得重載很多個,比如針對魯班,就得有一個大招方法。針對蘭陵王,又需要一個大招方法。這樣會導致方法特別多,而且不易維護。如果,我們直接設定所有的英雄都必須繼承自英雄類,那么,大招方法,只需要一個英雄類的參數即可,一個方法足以。

所以,多態的好處,我認為,就是方便傳參。而且,更多的,在設計類的時候,就應該預想到會有什么類型的參數傳進來,這是需要提前考慮的。


個人博客:http://java520.top/

點擊查看更多內容
18人點贊

若覺得本文不錯,就分享一下吧!

評論

相關文章推薦

正在加載中
意見反饋 幫助中心 APP下載
官方微信

舉報

0/150
提交
取消
lpl竞猜