Java: 如何编写泛型方法?

Java: How do I write a generic method?

假设我有几个 Creature sub类,并且它们每个都有某种 getGroup() 方法 returns a List<Creature> .

我说的"some sort of".getGroup()方法的意思是这个函数的名字在sub类之间是不一样的。例如,Wolf 成群结队旅行,因此他们有一个 getPack() 成员。 Fish在学校出差,所以他们有.getSchool()个会员,HumansgetFamily()个会员,依此类推。

.getGroup()Creature中不存在,无法添加到界面中。 None 个类别可以编辑。

我正在编写一种方法来打印他们组中 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();
    }

我想我需要将第二个参数(函数指针?)传递给 void printGroupSize。非常感谢任何帮助,谢谢!

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

唯一的答案是使用通用函数(如果存在的话)。 我实际使用的 类 没有通用接口,但它们都有一个功能,即 returns 一个列表。

你在问题中描述的内容与Java对"generic methods"的感觉没有太大关系。你可以用反射来实现它(见 Class.getMethod()),但我向你保证你真的不想去那里。

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

如果无法将 getGroup 添加到 Creature 接口,为什么不为您的生物添加另一个接口?

public interface HasGroup {
    Group getGroup();
}

这意味着您可以创建方法:

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

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

如果您可以修改子类,我实际上会创建一个带有 getGroupSize() and/or getGroup() 的新接口 CreatureGroupableCreature 的每个子类都应实现此接口,例如

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 组层次结构。

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

  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*****() 函数 return a List<Creature>。此解决方案还显着缩小了我的代码库,并且比当前结构更易于维护。