在Java中动态转换对象?

3

我有一个抽象类Entity,它有几个子类:SubclassASubclassBSubclassA还有一个子类SubSubClass

我也有一个类为SomeClass的对象someObject,它长这样:

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

事情是这样的,无论当前Entity的实际类型是什么,doSomething(Entity e)总是被调用,因为引用类型总是Entity。为了解决这个问题,我需要进行类型转换,例如:someObject.doSomething((SubclassB)entity)
所以我想知道是否有一种方法可以将对象动态地转换为其具体类型,而不需要使用instanceof操作。
如果没有办法做到这一点,你会如何处理我的情况?
6个回答

5

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


4
如果你发现自己想要强制转换一个对象,那么你可能已经犯了错误。
你的问题在于期望编写能够处理对象的代码,而实际上应该教会这个对象如何去处理它自己。这是面向对象编程的核心原则之一。
看起来很简单吧:
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);
    }
}

1
个人而言,我会编写一个单一的doSomething(Entity e)函数,然后在其中使用instanceof确定子类。很抱歉我无法提供避免使用instanceof的解决方案。如果不了解您项目的更多信息,这似乎是一个足够简单的解决方案。希望这可以帮助您!

0

0

这感觉像是违反了面向对象原则。

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

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


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块,但它仍然是一个解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接