開發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 blood 到 penta 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();
}
這就是所謂的多態。
從這個例子當中,我們可以看出,多態最直接的好處就是某個方法中,同一個參數可以接收多種類型的數據。
比如剛才大喬的例子,如果我們不用多態,那么大招方法就得重載很多個,比如針對魯班,就得有一個大招方法。針對蘭陵王,又需要一個大招方法。這樣會導致方法特別多,而且不易維護。如果,我們直接設定所有的英雄都必須繼承自英雄類,那么,大招方法,只需要一個英雄類的參數即可,一個方法足以。
所以,多態的好處,我認為,就是方便傳參。而且,更多的,在設計類的時候,就應該預想到會有什么類型的參數傳進來,這是需要提前考慮的。
作業:
用面向對象的思維來描述以下的現象:
蘭陵王被王昭君的大招凍住了,結果對方的項羽把蘭陵王推了出去!
提示:
蘭陵王,王昭君,項羽 都應該繼承自Hero類。
個人博客:http://java520.top/