2012-07-30 26 views
3

我想在Java中實現函數對象。我有一個Unit類,它有一個默認的附加函數,應該在Unit對象的大多數初始化中使用。但是,對於一些問題,我需要一個不同的附加功能。該代碼將是這個樣子:使用java中的對象功能

public class Unit() { 
    public Unit(unitType) { 
     if (unitType == "specialType") { 
     additionFunc = defaultFunc } else { 
     additionFunc = specialFunc } 
     } 
    } 
    public int swim() { 
     return additionFunc() 
    } 
    // definiion of regularFunc 
    // definition of specialFunc 

} 

然後,從主文件:

Unit fish = new Unit(regularTyoe); 
Unit fatFish = new Unit(specialType); 
fish.swim(); //regular function is called 
fatFish.swim(); //special function is called 

就是這樣..沒有人知道如何可以做到這一點?

回答

1

我認爲它可以做延伸和工廠方法:

公共類股{

public static Unit createUnit(UnitType type) { 
    if (UnitType.Special == type) { 
     return new Unit(type) { 
      @Override 
      public int swim() { 
       System.out.println("special swim"); 
       return 0; 
      } 
     }; 
    } 
    return new Unit(UnitType.Default); 
} 

private UnitType type; 

private Unit(UnitType type) { 
    this.type = type; 
    System.out.println("create unit for " + type); 
} 

public int swim() { 
    System.out.println("default swim"); 
    return 0; 
} 

public static void main(String[] args) { 
    Unit fish = Unit.createUnit(UnitType.Default); 
    Unit fatFish = Unit.createUnit(UnitType.Special); 
    fish.swim(); 
    fatFish.swim(); 

} 

}

這是一個簡單枚舉類型:

公共枚舉UNITTYPE { 默認,特別

}

+0

所有這些答案都讓我感覺不到比以往:) 這似乎是最接近我所需要的,謝謝! – 2012-07-30 16:11:33

2

創建一個擴展Unit並覆蓋swim()的新FatFish類。

Unit fish = new Unit(); 
Unit fatFish = new FatFish(); 
fish.swim(); //regular function is called 
fatFish.swim(); //special function is called 
4

您需要查看inheritancemethod overriding。這也可能有助於閱讀正確的面向對象編程。

正確的方式做,這就是:

class Fish { 
    public void swim() { 
    // normal swim 
    } 
} 

class FatFish extends Fish { 
    @Override 
    public void swim() { 
    // special swim 
    } 
} 

Fish fish = new Fish() 
Fish fatFish = new FatFish() 
fish.swim() // normal swim 
fatFish.swim() // slow swim 
+0

這是唯一的辦法?在java中沒有函數對象? :(( – 2012-07-30 15:38:28

+0

@ n00bprogrammer ....函數不是Java中的第一類對象,雖然有辦法破解你想做的事情,但是在每個級別上都是錯誤的方法 – 2012-07-30 15:40:26

1

使用簡單的if語句:

private String unitType; 

public Unit(unitType) { 
    this.unitType = unitType;  
} 

public int swim() { 
    if (unitType.equals("specialType") { 
     return specialFunc(); 
    } 
    else { 
     return regularFunc(); 
    } 
} 

或者使用多態和工廠方法:

public abstract class Unit() { 

    protected Unit() { 
    } 

    protected abstract int addition(); 

    public int swim() { 
     return addition(); 
    } 

    public static Unit forType(String unitType) { 
     if (unitType.equals("specialType") { 
      return new SpecialUnit(); 
     } 
     else { 
      return new RegularUnit(); 
     } 
    } 

    private static class SpecialUnit extends Unit { 
     @Override 
     protected addition() { 
      // special addition 
     } 
    } 


    private static class RegularUnit extends Unit { 
     @Override 
     protected addition() { 
      // regular addition 
     } 
    } 
} 

或使用Adder功能接口,定義了一個addition()方法,以及兩個co這個接口的分立實現:

private Adder adder; 

public Unit(unitType) { 
    if (unitType.equals("specialType") { 
     this.adder = new SpecialAdder(); 
    } 
    else { 
     this.adder = new RegularAdder(); 
    } 
} 

public int swim() { 
    return adder.addition(); 
} 

這最後一個是最接近你問你的問題。函數對象本身不存在,但可以由接口替換。

1

有兩種方法可以在Java中完成這種多態行爲。首先是使用繼承和分層的一組類。例如,你可以有一個抽象基類,它定義了一個叫做「游泳」的抽象方法。然後每個具體的魚類將擴展這個基類並實現游泳方法。稍後,當您有一組魚對象時,可以將它們上傳到基類並調用每個對象的游泳方法。

第二種方法是使用接口。您定義了一個聲明公共方法遊動的接口(例如ISwim)。每個魚類(無論是否是類層次結構的一部分)都將實現ISwim接口,這意味着它們將定義一個游泳方法。然後,如果您有一組不同類型的魚類對象,則可以將其轉換爲ISwim接口並調用每個對象的游泳方法。

Java沒有函數指針,所以您正在考慮的方法對於該語言不適用。即使在使用函數指針的語言中,上述兩種方法在我看來也是最合適的。要做到這一點

1

一種方法是用enum的類型UnitUnit子類:

public class Unit { 
    public enum UnitType { 
     REGULAR { 
      public Unit makeUnit() { 
       return new RegularUnit(); 
      } 
     }, 
     SPECIAL { 
      public Unit makeUnit() { 
       return new SpecialUnit(); 
      } 
     }; 
     abstract public Unit makeUnit(); 
    } 
    protected Unit() {} 
    public abstract int swim(); 
    private static class RegularUnit extends Unit { 
     RegularUnit() {} 
     public int swim() { 
      return 0; 
     } 
    } 
    private static class SpecialUnit extends Unit { 
     SpecialUnit() {} 
     public int swim() { 
      return 1; 
     } 
    } 
} 

Unit fish = UnitType.REGULAR.makeUnit(); 
Unit fatFish = UnitType.SPECIAL.makeUnit(); 

另一種方法是用Callable對象:

public class Unit { 
    public enum UnitType { REGULAR, SPECIAL } 
    private Callable<Integer> additionFunc; 
    public Unit(UnitType type) { 
     switch (type) { 
     case REGULAR: 
      additionFunc = new Callable<Integer>() { 
       public Integer call() { 
        return 0; 
       } 
      }; 
      break; 
     case SPECIAL: 
      additionFunc = new Callable<Integer>() { 
       public Integer call() { 
        return 1; 
       } 
      }; 
      break; 
     } 
    } 
    public int swim() { 
     return additionFunc(); 
    } 
} 
2

針對您的問題有許多解決方案,其中一個使用繼承,您可以使用Unit的默認實現,並將其擴展爲使用新方法覆蓋所需的方法。

基本上會是這樣的:

public class FatFish { 
    @Override 
    public void swim() { 
     // new behavior 
    } 
} 

另一種方法是實現Strategy Design Pattern,它允許您選擇在運行時的算法。因此,你可以這樣做:

public interface SwimStrategy { 
    void execute(); 
} 

public class FatFishSwimStrategy implements SwimStrategy { 
    @Override 
    public void execute() { 
     // fat fish swim impl 
    } 

} 

public class FishSwimStrategy implements SwimStrategy { 
    @Override 
    public void execute() { 
     // normal fish swim impl 
    } 

} 

public class Fish { 

    private final SwimStrategy swimStrategy; 

    public Fish(SwimStrategy swimStrategy) { 
     this.swimStrategy = swimStrategy; 
    } 

    public void swim() { 
     swimStrategy.execute(); 
    } 

} 

爲了實例化一個對象,你可以這樣做:

new Fish(new FatFishSwimStrategy()); 

或爲正常行爲:

new Fish(new FishSwimStrategy()); 
+0

我覺得你的界面'SwimStrategy'應該有'void swim()'而不是'void execute()'? – 2012-07-30 15:46:59

+0

我剛剛改正了;)但是非常感謝 – 2012-07-30 15:48:35