简体   繁体   English

Java:如何编写通用方法?

[英]Java: How do I write a generic method?

let's say that I have several Creature subclasses, and that they have each have some sort of getGroup() method that returns a List<Creature> . 假设我有几个Creature子类,并且每个子类都有某种getGroup()方法,这些方法返回List<Creature>

What I mean by "some sort of" .getGroup() method is that the name of this function varies between subclasses. .getGroup() 的“ .getGroup()方法”的 .getGroup()是该函数的名称在子类之间有所不同。 For instance, Wolf s travel in packs, so they have a getPack() member. 例如, Wolf打包旅行,因此他们有一个getPack()成员。 Fish travel in schools, so they have a .getSchool() member, Humans have a getFamily() member, and so on. Fish在学校旅行,所以他们有一个.getSchool()成员, Humans有一个getFamily()成员,依此类推。

.getGroup() doesn not exist in Creature , and it cannot be added to the interface. .getGroup()Creature不存在,因此无法将其添加到接口中。 None of these clases can be edited. 这些小节均无法编辑。

I'm writing a method to print the number of Creature s in their group. 我正在编写一种方法来打印其组中Creature的数量。 How would I do this? 我该怎么做?

Essentially, I'm looking to condense these two functions into the same thing: 本质上,我希望将这两个函数压缩为同一件事:

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

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

...into the following function: ...转换为以下功能:

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

I'd imagine I need to pass in a second argument (function pointer?) to void printGroupSize . 我以为我需要传入第二个参数(函数指针?)以void printGroupSize Any help is very appreciated, thanks! 任何帮助都非常感谢,谢谢!

EDIT Thank you all for the help. 编辑谢谢大家的帮助。 This is just a simplification of the real problem I'm trying to solve. 这只是我要解决的实际问题的简化。 Long, overly complex problems are tougher to answer, so I posed this simpler scenario. 长期的,过于复杂的问题很难回答,因此我提出了一个更简单的方案。

The only answer lies in using a generic function (if that exists). 唯一的答案在于使用泛型函数(如果存在)。 The classes I'm actually working with don't have a common interface, but they all have a function that returns a List. 我实际上正在使用的类没有通用接口,但是它们都有一个返回List的函数。

What you describe in your question is not much related to Java's sense of "generic methods". 您在问题中描述的内容与Java的“泛型方法”感没有太大关系。 You could implement it with reflection (see Class.getMethod()), but I promise you that you really don't want to go there. 您可以通过反射来实现它(请参阅Class.getMethod()),但是我向您保证,您真的不想去那里。

It would be better for Creature to declare a possibly- abstract method getGroup() that each subclass would override. 对于Creature ,最好声明每个子类将覆盖的可能abstract方法getGroup() You may do that in addition to providing methods with subclass-specific names, if you wish. 如果愿意,除了提供具有特定于子类名称的方法外,您还可以这样做。 Code that wants to obtain the group (or its size) without knowing the specific type of creature would invoke that creature's getGroup() method. 想要在不知道生物特定类型的情况下获取组(或其大小)的代码将调用该生物的getGroup()方法。 That's an application of polymorphism , which seems to be what you're actually after. 那是多态性的一种应用,这似乎正是您真正追求的。

If getGroup cannot be added to the Creature interface why not add another interface to your creatures? 如果无法将getGroup添加到Creature接口,为什么不向您的生物添加另一个接口?

public interface HasGroup {
    Group getGroup();
}

Would mean you can create the method: 这意味着您可以创建方法:

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

The simplest way is to had a getGroup() method to the Creature interface and implement it in each subclass, but it seems you cannot do that. 最简单的方法是对Creature接口使用getGroup()方法,并在每个子类中实现它,但是看来您无法做到这一点。

If you can modify the subclasses, I would actually create a new interface CreatureGroupable with a getGroupSize() and/or getGroup() . 如果可以修改子类,则实际上我将使用getGroupSize()和/或getGroup()创建一个新接口CreatureGroupable Each subclass of Creature shall implement this interface, eg 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;
}

This way, if you have a List<Creature> you can access the group of each one and do whatever you have to do, eg 这样,如果您有一个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.");    
   }
}

If you want more flexibility, you may not use an enum and just a standard interface and class hierarchy for the groups. 如果需要更大的灵活性,则可以不为组使用enum而仅使用标准interfaceclass层次结构。

Thanks to everyone for the help. 感谢大家的帮助。 Since I'm not allowed to edit any of the aforementioned classes/interfaces (I can only write external functions), I wrote the following function 由于不允许编辑上述任何类/接口(我只能编写外部函数),因此编写了以下函数

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

...and used it here, as so: ...并在这里使用它,如下所示:

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

I have verified that this solution does indeed work, since all of the get*****() functions return a List<Creature> . 我已经验证了该解决方案的确有效,因为所有的get *****()函数都返回List<Creature> This solution also shrinks my codebase significantly, and is easier to maintain than the current structure. 该解决方案还大大缩减了我的代码库,并且比当前结构更易于维护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM