Java:如何编写泛型方法?

时间:2015-02-18 22:04:09

标签: java generics

假设我有几个Creature个子类,并且每个子类都有某种返回getGroup()的{​​{1}}方法。

我的意思是“某种” List<Creature>方法,这个函数的名称在子类之间有所不同。例如,.getGroup()包裹旅行,因此他们有一个Wolf成员。 getPack()在学校旅行,因此他们有Fish个成员,.getSchool()Humans个成员,等等。

getFamily().getGroup()中不存在,并且无法添加到界面中。这些条款都不能编辑。

我正在编写一种方法来打印其组中Creature的数量。我该怎么做?

基本上,我希望将这两个函数压缩成相同的东西:

Creature

...进入以下功能:

    public void PrintSchoolSize(Fish dory) {
        System.out.print(dory.getSchool().size());
    }

    public void PrintHiveSize(Bee bee) {
        System.out.print(bee.getColony().size());
    }

我想我需要将第二个参数(函数指针?)传递给 public void printGroupSize( Class<? extends Creature> cree, FunctionThatReturnsList getGroup() ) { System.out.print(cree.getGroup().size(); } 。非常感谢任何帮助,谢谢!

编辑谢谢大家的帮助。这只是我试图解决的真实问题的简化。很长,过于复杂的问题难以回答,所以我提出了这个更简单的方案。

唯一的答案在于使用泛型函数(如果存在)。我实际使用的类没有通用接口,但它们都有一个返回a的函数列表。

4 个答案:

答案 0 :(得分:3)

您在问题中描述的内容与Java的“通用方法”意义无关。你可以用反射来实现它(参见Class.getMethod()),但我保证你真的不想去那里。

Creature最好声明每个子类将覆盖的可能 - abstract方法getGroup()。如果您愿意,除了提供具有子类特定名称的方法之外,您可以这样做。想要在不知道特定类型的生物的情况下获取组(或其大小)的代码将调用该生物的getGroup()方法。这是多态性的应用,这似乎就是你实际所追求的。

答案 1 :(得分:0)

如果无法将getGroup添加到Creature界面,为什么不为生物添加另一个界面?

public interface HasGroup {
    Group getGroup();
}

意味着你可以创建方法:

public void printGroupSize(HasGroup cree) {
    System.out.print(cree.getGroup().size();
}

答案 2 :(得分:0)

最简单的方法是在getGroup()接口中使用Creature方法并在每个子类中实现它,但似乎你不能这样做。

如果你可以修改子类,我实际上会创建一个带有CreatureGroupable和/或getGroupSize()的新接口getGroup()Creature的每个子类都应实现此接口,例如

public interface CreatureGroupable {
   CreatureGroup getGroup();
}

public enum CreatureGroup {
   WOLF_PACK("pack", 30), 
   GEES_FLOCK("flock", 20),
   FISH_SCHOOL("school", 1000),
   HUMAN_FAMILY("family", 4),
   ...
   private final String name;
   private final int size;

   private CreatureGroup(String name, int size) {
     this.name = name;
     this.size = size; 
   }

   public String getName() { return name; }
   public int getSize() { return size; }
}

public class Wolf implements Creature, CreatureGroupable {
   // methods from Creature, constructor, ...

   public CreatureGroup getGroup() {
      return CreatureGroup.WOLF_PACK;
}

这样,如果您有一个List<Creature>,您可以访问每个组的组并执行您必须做的任何事情,例如。

public void printGroups(List<Creature> creatures) {
   for (Creature c : creatures) {
      CreatureGroup group = c.getGroup();
      System.out.println("A " + group.getName() + 
                         " has roughly " group.getSize() + 
                         " individuals.");    
   }
}

如果您希望获得更大的灵活性,则可能不会使用enum,只能使用标准interfaceclass层次结构。

答案 3 :(得分:0)

感谢大家的帮助。由于我不允许编辑任何上述类/接口(我只能编写外部函数),我编写了以下函数

  public List<? extends Creature> getGroup(Object obj) {

      if(obj.getClass() == Bee.class)
          return ((Bee)obj).getColony();

      if(obj.getClass() == Fish.class)
          return ((Fish) obj).getSchool();

      /* repeat for the other classes */

      return null;
  }

......并在这里使用它,如下:

   public void printGroupSize( Class<? extends Creature> cree ) {
       System.out.print(getGroup(cree).size());
   }

我已经验证此解决方案确实有效,因为所有get *****()函数都返回List<Creature>。此解决方案还显着缩小了我的代码库,并且比当前结构更易于维护。