【问题标题】:using object functions in java在java中使用对象函数
【发布时间】:2012-07-28 07:15:40
【问题描述】:

我正在尝试在 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

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

【问题讨论】:

    标签: java function object


    【解决方案1】:

    您需要查找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
    

    【讨论】:

    • 这是唯一的方法吗? java中没有函数对象? :((
    • @n00bprogrammer .... 函数不是 Java 中的一流对象。虽然有很多方法可以破解您正在尝试做的事情,但在各个层面上都是错误的方法。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      您的问题有很多解决方案,其中之一是使用继承,您可以拥有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());
      

      【讨论】:

      • 我认为你的界面SwimStrategy应该有void swim()而不是void execute()
      【解决方案4】:

      我认为可以通过扩展和工厂方法来做到:

      公共课单元{

      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 { 默认,特殊

      }

      【讨论】:

      • 所有这些答案让我感觉比以往任何时候都更无聊 :) 这似乎是最接近我需要的,谢谢!
      【解决方案5】:

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

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

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

      【讨论】:

        【解决方案6】:

        一种方法是使用enum 来表示Unit 的类型和Unit 子类:

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

        【讨论】:

          【解决方案7】:

          使用简单的 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();
          }
          

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

          【讨论】:

            猜你喜欢
            • 2016-08-20
            • 2015-01-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多