简体   繁体   English

如何制作一个可以接受任何类型参数的 Java 类

[英]How to make a Java class that can take parameters of any type

I'm making a plugin that handles Quests in a game.我正在制作一个处理游戏中任务的插件。 I have a Quest class that is the instance of a Quest, this is attached to the player's object.我有一个 Quest 类,它是 Quest 的实例,它附加到玩家的对象。 I can get the Quest, check it's objectives, which are complete and which aren't etc.我可以得到任务,检查它的目标,哪些是完整的,哪些不是等等。

I have four types of Objectives (Talk, Kill Entity, Collect Item, Craft Item).我有四种类型的目标(谈话、杀死实体、收集物品、制作物品)。 This is stored in an enum.这存储在枚举中。 I'm trying to figure out how I can make my Objective class as efficiently as possible, this would require me to init the Objective class with the objective type then the target (the NPC to talk to or the item to collect etc.) but the target would be of a different type depending on the ObjectiveType.我试图弄清楚如何使我的目标类尽可能高效,这将需要我用目标类型然后目标(要与之交谈的 NPC 或要收集的物品等)来初始化目标类,但是根据ObjectiveType,目标将是不同的类型。

eg: Objective newObjective = new Objective(ObjectiveType.TALK, NPC(10));例如: Objective newObjective = new Objective(ObjectiveType.TALK, NPC(10)); would create an objective telling the player to talk to the NPC with the ID 10将创建一个目标,告诉玩家与 ID 为 10 的 NPC 交谈

Objective newObjective = new Objective(ObjectiveType.COLLECT_ITEM, Item(ZOMBIE_ESSENCE)); would create an objective telling the player to collect one Zombie Essence.会创建一个目标,告诉玩家收集一个僵尸精华。

Any help is much appreciated.任何帮助深表感谢。

Enums cannot be have their own generic types yet (I think there is a JSR for that though).枚举还不能有自己的泛型类型(我认为有一个 JSR)。 That means that you cannot really tie the ObjectiveType and its argument together.这意味着您不能真正将ObjectiveType及其参数联系在一起。 Otherwise, you could have made Objective generic:否则,您可以将Objective设为通用:

// this is not possible yet
enum ObjectiveType<T> {
    TALK<NPC>,
    COLLECT_ITEM<Item>,
    ...
}

class Objective<T> {
    public Objective(ObjectiveType<T> type, T argument) { ... }
}

However, what you can easily do is make the constructor(s) private and use factory methods:但是,您可以轻松地将构造函数设为私有并使用工厂方法:

public static Objective newTalkObjective(NPC npc) {
    return new Objective(ObjectiveType.TALK, npc);
}

public static Objective newCollectItemObjective(Item item) {
    return new Objective(ObjectiveType.COLLECT_ITEM, item);
}

Assuming that NPC and item are classes I can think of a number of ways to do this: Create multiple constructors:假设 NPC 和 item 是类,我可以想到多种方法来做到这一点: 创建多个构造函数:

public Objective(NPC npc){
...
}

public Objective(Item item){
...
}

The constructor used will also indicate the type of objective.使用的构造函数还将指示目标的类型。 So, no need to pass that in.所以,没必要传进去。

A second way would be to make NPC and Item extend a base class.第二种方法是让 NPC 和 Item 扩展一个基类。 In this way you will only need one constructor for Objective with the second parameter being the of the type of the base class.这样,您将只需要一个用于 Objective 的构造函数,第二个参数是基类的类型。

But, IMHO, the correct way to go is actualy to have Objective as a base class and extend it for each type of objective.但是,恕我直言,正确的做法实际上是将 Objective 作为基类并为每种类型的目标扩展它。 This will make the code MUCH clearer.这将使代码更清晰。 Any shared values and methods would go in the base class and the specific ones per objective type would go in the child class.任何共享值和方法都将放在基类中,每个目标类型的特定值和方法将放在子类中。

It will also make it much easier to add more objective types in the future because all you have to do is create another class that extends Objective.它还将使将来添加更多目标类型变得更加容易,因为您所要做的就是创建另一个扩展目标的类。

idea 1 - sub-class of Objective想法 1 - Objective的子类

Any Objective instance is very similar to a Event instance.任何Objective实例都与Event实例非常相似。

A common design of EventBus is use a sub-class tree to describe any EventType s. EventBus 的一个常见设计是使用子类树来描述任何EventType

This should be efficient if you take enough abstraction of whole Objective module: BaseObjective , EntityObjective , MonsterObjective , KillMonsterObjective ...如果您对整个 Objective 模块进行足够的抽象,这应该是有效的: BaseObjectiveEntityObjectiveMonsterObjectiveKillMonsterObjective ...

class Objective
{
  ObjectiveType type;
  public Objective(ObjectType type) { this.type = type; }
}

class ObjectiveKillTarget extends Objective
{
  TargetType typeTarget; // any extra parameters
  public ObjectiveKillTarget(TargetType typeTarget)
  {
    super(ObjectiveType.KILL_TARGET);
    this.typeTarget = typeTarget;
  }
}

idea 2 - store key-value-pair in Map<String, ?> or something like that想法 2 - 将键值对存储在Map<String, ?>或类似的东西中

If you DO want to store all data into instances of ONE class, Map<String, ?> could help.如果您确实想将所有数据存储到 ONE 类的实例中, Map<String, ?>可能会有所帮助。

It is not recommended but works.不推荐但有效。

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

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