用Java动态地转换对象?

时间:2014-06-16 15:47:20

标签: java casting

我有一个带有几个子类的抽象类EntitySubclassASubclassBSubclassA有一个子类SubSubClass

我还有类someObject的对象SomeClass,如下所示:

class SomeClass{
    void doSomething(Entity e){..}
    void doSomething(SubclassA e){..}
    void doSomething(SubclassB e){..}
    void doSomething(SubSubClass e){..}
}

我有List<Entity> list。此列表中的每个项目都会传递到someObject.doSomething

for(Entity entity : list){
    someObject.doSomething(entity);
}

事情是,总是调用doSomething(Entity e),无论当前Entity的实际类型是什么,因为引用类型始终是Entity。要解决这个问题,我需要进行投射,例如:someObject.doSomething((SubclassB)entity)

所以我想知道是否有一种方法可以动态地将对象强制转换为任何具体类型,而无需instanceof次操作。

如果无法做到这一点,你会如何处理我的情况?

6 个答案:

答案 0 :(得分:5)

翻转它,将receiveWork(或任何你想要命名的)方法(可能需要Runnable或其他可执行单元)添加到Entity及其子类并调用foreach循环中的方法。让多态为你工作。

答案 1 :(得分:4)

如果你发现自己想要施放一个物体,你可能已经做错了。

你的错误是期望编写与对象有关的代码 - 相反,你应该教会对象如何自己做。这是oop的核心原则。

看看它有多简单:

class Entity {

    public void action(SomeClass c) {
        c.doSomething(this);
    }
}

class SubclassA extends Entity {

    public void action(SomeClass c) {
        c.doSomething(this);
    }
}

class SubclassB extends Entity {

    public void action(SomeClass c) {
        c.doSomething(this);
    }
}

class SubSubClass extends SubclassA {

    public void action(SomeClass c) {
        c.doSomething(this);
    }
}

class SomeClass {

    void doSomething(Entity e) {
        System.out.println("Do something (Entity) with an " + e.getClass());
    }

    void doSomething(SubclassA e) {
        System.out.println("Do something (SubclassA) with an " + e.getClass());
    }

    void doSomething(SubclassB e) {
        System.out.println("Do something (SubclassB) with an " + e.getClass());
    }

    void doSomething(SubSubClass e) {
        System.out.println("Do something (SubSubClass) with an " + e.getClass());
    }
}

public void test() {
    List<Entity> list = new ArrayList<>();
    list.add(new Entity());
    list.add(new SubclassA());
    list.add(new SubclassB());
    list.add(new SubSubClass());
    SomeClass someObject = new SomeClass();
    for (Entity entity : list) {
        entity.action(someObject);
    }
}

答案 2 :(得分:1)

就个人而言,我会编写一个单一的doSomething(Entity e)函数,然后在其中使用instanceof确定子类。对不起,我无法为您的问题提供解决方案,避免出现问题。在不了解有关您的项目的更多信息的情况下,我认为这将是一个简单的解决方案。希望这有帮助!

答案 3 :(得分:0)

您似乎应该在这里使用访客模式。有关详细信息,请查看此文章:http://en.wikipedia.org/wiki/Visitor_pattern

答案 4 :(得分:0)

这感觉违反了OO原则。

为什么这些方法没有委托给子类?

通过将doSomething附加到Entity并覆盖它,我在Someclass中的方法可以简单地委托,获取实体并调用entity.doSomething()。这将自动调用正确的方法。通过多态性。

答案 5 :(得分:0)

现在,我不知道这是否是您想要的,但由于您不想使用instanceof,我个人会将所有实体强制转换为最低的子类并让您的doSomething如果接收到错误的对象,则抛出异常。然后,当抛出异常时,我会抓住它。在catch块中,我将相同的对象(向上一级)传递给方法。

for(Entity entity : list){
   try {
      doSomething((SubSubclass)entity);
   } catch (SomeException e) {
      try {
         doSomething((SubClassA)entity); //I believe that this throws a ClassCastException of the object is actually a SubClassB...
      } catch (SomeException e) {
         try {
            //etc. etc...

同样,我不知道这是否是您想要的,并且它使用了一堆嵌套的try catch块,但它仍然是一个解决方案。