简体   繁体   English

java - 从动态转换的超类中调用子类方法

[英]java - Calling a subclass method from dynamically casted superclass

1: 1:

I have a dictionary with a string as key and a class as value, this contains a list of "entities" i have in my game. 我有一个字典,字符串作为键,类作为值,这包含我在游戏中的“实体”列表。

private static Map<String, Class> entitiesList = new HashMap<String, Class>();
public static void initEntitiesList()
{
    entitiesList.put("npc_something", NpcSomething.class);
    entitiesList.put("npc_thing", NpcThing.class);
    entitiesList.put("npc_stuff", NpcStuff.class);
    ...
}

2: 2:

Here's an example hierarchy. 这是一个示例层次结构。

Entity (abstract)
^
Mobile (abstract)
^
BaseCreature (abstract)
^
NpcSomething

-Entity contains a method called "public void Input(String args)" , which can be redefined in the other entities. -Entity包含一个名为"public void Input(String args)" ,可以在其他实体中重新定义。
-When i call Input("x") on NpcSomething it should do a super(arg) chain from it's own class to Entity's class. - 当我在NpcSomething上调用Input("x") ,它应该从它自己的类到Entity的类执行super(arg)链。
-All those classes above have a constructor allowing string as argument. - 上面的所有类都有一个允许字符串作为参数的构造函数。

3: 3:

I have an independent static method used to create new instances of my entities, which goes as such: 我有一个独立的静态方法用于创建我的实体的新实例,如下所示:

public static boolean createEntity(String entName, String args)
{
    Class<?> entClass = null;
    if ((entClass = entitiesList.get(entName)) != null)
    {
        Entity ent;
        try
        {
            ent = (Entity)entClass.getDeclaredConstructor(String.class).newInstance("");

            //this here failed.
            //Method method = entClass.getMethod("input", new Class[] { ent.getClass() });
            //method.invoke(ent, new Object[] {ent});
            //java.lang.NoSuchMethodException: entities.NpcSomething.input(entities.NpcSomething)

            //this here is really out of place, as i plan on having a hundred of entities and even more...
            //if (entClass.isInstance(NpcSomething.class))

            //i tried stuffs related to:
            //T t = entClass.cast(ent);
            //but i could not understand it at all even with documentation.

            //basically i want to cast ent to entClass to call Input.
            //right now, the line under calls Input on an Entity class, which is what i want to avoid.
            ent.Input("Stuffs");
        }
        catch (InstantiationException ex) { ex.printStackTrace(); }
        catch (IllegalAccessException ex) { ex.printStackTrace(); }
        catch (IllegalArgumentException ex) { ex.printStackTrace(); }
        catch (InvocationTargetException ex) { ex.printStackTrace(); }
        catch (NoSuchMethodException ex) { ex.printStackTrace(); }
        catch (SecurityException ex) { ex.printStackTrace(); }
    }
}

4: 4:

My problem. 我的问题。

EntCreator.createEntity("NpcSomething", "stuffs");
EntCreator.createEntity("NpcThing", "stuffs");
EntCreator.createEntity("NpcStuff", "stuffs");

I want to call Input(); 我想调用Input(); on NpcSomething, 在NpcSomething上,
I want to call Input(); 我想调用Input(); on NpcThing, 在NpcThing上,
I want to call Input(); 我想调用Input(); on NpcStuff. 在NpcStuff上。
Then those 3 will call their respective superclass code, and so on until they reach Entity. 然后那些3将调用它们各自的超类代码,依此类推,直到它们到达实体。

Those are casted as Entity with "ent = (Entity)entClass.getDec..." , because i have Mobile, but also Item, and other classes that inherit Input. 那些被转换为实体,带有"ent = (Entity)entClass.getDec..." ,因为我有Mobile,还有Item,以及其他继承Input的类。 Then with that Entity, find the right subclass, and call the Input of that said subclass. 然后使用该Entity,找到正确的子类,并调用该子类的Input。

Short line problem: Create "NpcSomething" as an "Entity" then cast the entity to "NpcSomething's class" to call the method "Input(args)" . 短线问题:将“NpcSomething”创建为“Entity”,然后将实体强制转换为“NpcSomething的类”以调用方法"Input(args)"

5: 5:

Answers to quick questions. 快速问题的答案。

-Q: Why doing this? -Q:为什么要这样做?
-A: To create entities with pre-creation arguments, example: creating a ("NpcSomething", "health 20 healthmax 25") . -A:使用预创建参数创建实体,例如:创建("NpcSomething", "health 20 healthmax 25")

-Q: Why not using instanceof? -Q:为什么不使用instanceof?
-A: I would need more than 200 instanceof in that static class, this would be a bad programming practice. -A:在静态类中我需要超过200个instanceof ,这将是一个糟糕的编程习惯。

-Q: Why don't you move your input method in Entity itself? -Q:为什么不在实体本身中移动输入法?
-A: I have many different entities with different values, ex: NpcThing, the only flying mobile would have flyingSpeed, flyingEnergy... ItemScroll, having text, textColor, textFont... Those are things i can't place in Entity, as it would require instanceof , which is a bad practice for more than ents. -A:我有很多不同的实体有不同的值,例如:NpcThing,唯一的飞行手机会有flyingSpeed,flyingEnergy ... ItemScroll,有text,textColor,textFont ......这些是我无法放入实体的东西,因为它需要instanceof ,这对于ents而言是一种不好的做法。

-Q: Do you want to cast NpcSomething to Entity? -Q:你想将NpcSomething投射到实体吗?
-A: Read the whole thing again. -A:再读一遍。

-Q: Could you provide more informations? -Q:你能提供更多信息吗?
-A: I would love to do that too. -A:我也喜欢这样做。

-Q: Why don't you declare ent as NpcSomething? -Q:你为什么不宣布为NpcSomething?
-A: because ent could be ItemStuff, ModelHouse, etc, which are not inheriting from Mobile, or BaseCreature... -A:因为ent可能是ItemStuff,ModelHouse等,它们不是继承自Mobile或BaseCreature ......

6: 6:

I did not find good practical examples of how to do what i want. 我没有找到如何做我想要的好的实际例子。
I could not find anything especially for this in the documentation. 我在文档中找不到任何特别的内容。
Any help is welcome. 欢迎任何帮助。

Suppose you got the Entity ent instance from newInstance() method. 假设您从newInstance()方法获得了Entity ent实例。 This is how you invoke input(String) method for that instance: 这是您为该实例调用input(String)方法的方法:

// See here, the .class argument passed is the type of parameter
// You're using `ent.getClass()` here. It won't work
Method method = ent.getMethod("input", String.class);

// then while invoking this method, you pass the argument:
// Call `invoke()` method of `Method` class
// First arg is the instance on which this method should be called
// Remaining arg is the argument to be passed to the method itself.
result = method.invoke(ent, args);

Because the method call has a higher priority than the cast. 因为方法调用具有比强制转换更高的优先级。 You should force the cast before the method call by surrounding it with brackets 您应该在方法调用之前强制执行强制转换,方法是用括号括起它

ent = ((Entity)entClass).getDeclaredConstructor(String.class).newInstance("");

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

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