3

我正在尝试在 Java 中实现函数对象。我有一个 Unit 类,它有一个默认的添加函数,应该在 Unit 对象的大多数初始化中使用。但是,对于某些问题,我需要不同的添加功能。代码将如下所示:

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

就是这样..有谁知道如何做到这一点?

4

7 回答 7

4

您需要查找继承方法覆盖。阅读正确的面向对象编程也可能会有所帮助。

正确的方法是:

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
于 2012-07-30T15:37:00.800 回答
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());
于 2012-07-30T15:44:18.453 回答
2

创建一个新的 FatFish 类,它扩展了 Unit 并覆盖了 Swim()。

Unit fish = new Unit();
Unit fatFish = new FatFish();
fish.swim(); //regular function is called
fatFish.swim(); //special function is called
于 2012-07-30T15:33:37.680 回答
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 { 默认,特殊

}

于 2012-07-30T15:43:42.127 回答
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()方法,以及这个接口的两个具体实现:

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();
}

最后一个与您在问题中提出的最接近。函数对象本身不存在,但可以被接口替换。

于 2012-07-30T15:38:43.477 回答
1

在 Java 中有两种方法可以完成这种多态行为。第一种是使用继承和分层的类集。例如,您可以有一个抽象基类,它定义了一个名为“swim”的抽象方法。然后每个具体的鱼类将扩展这个基类并实现游泳方法。稍后当您有一组鱼对象时,您可以将它们向上转换到基类并在每个对象上调用游泳方法。

第二种方法是使用接口。你定义了一个接口(例如ISwim),它声明了公共方法swim。每个鱼类(无论是否属于类层次结构)都将实现 ISwim 接口,这意味着它们将定义一个游泳方法。然后,如果您有一组不同类型的鱼类对象,您可以将每个对象强制转换为 ISwim 接口并在每个对象上调用游泳方法。

Java 没有函数指针,因此您正在考虑的方法不适合该语言。即使在具有函数指针的语言中,我认为上述两种方法也是最合适的。

于 2012-07-30T15:39:30.380 回答
1

一种方法是使用enumfor 类型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();
    }
}
于 2012-07-30T15:39:32.883 回答