2012-07-30 57 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