Java,如何基于对象的一个接口重新转换对象?

Java,如何基于对象的一个接口重新转换对象?,java,interface,casting,Java,Interface,Casting,我有一组类实现接口Paintable和Tickable。 另一个类,World,通过将这些类推到ArrayList中来跟踪它们 我有一个不同的类,它处理所有可绘制的对象,获取所有这些对象的可靠方法是使用getPaintables()方法向world请求,因为world持有的所有对象都是可勾选和可绘制的 当我尝试将Tickable对象转换为Paintable对象时,出现了如下问题: for (Paintable p : (ArrayList<Paintable>)world.g

我有一组类实现接口
Paintable
Tickable
。 另一个类,
World
,通过将这些类推到
ArrayList
中来跟踪它们

我有一个不同的类,它处理所有
可绘制的对象,获取所有这些对象的可靠方法是使用getPaintables()方法向world请求,因为
world
持有的所有对象都是可勾选和可绘制的

当我尝试将
Tickable
对象转换为
Paintable
对象时,出现了如下问题:

    for (Paintable p : (ArrayList<Paintable>)world.getPaintables()) {
        // Do stuff
    }
for(Paintable p:(ArrayList)world.getpaintable()){
//做事
}
这导致:

    error: incompatible types: ArrayList<Tickable> cannot be converted to ArrayList<Paintable>.
错误:不兼容的类型:ArrayList无法转换为ArrayList。
有没有可能通过其他方式来解决这个问题?当然,我可以在
World
中复制
ArrayList
,一个作为
Paintable
,另一个作为
Tickable
,但这对我来说似乎很麻烦


我希望这是有道理的。

我不完全明白你的问题,但我会试一试

如果world.getPaintables()返回List,则很明显您的代码不起作用

如果world.getPaintables()同时包含这两个对象,则可以对可勾选和可绘制对象执行类似于Louis所说的操作:

for (Object p : (ArrayList<Object>)world.getPaintables()) {
    if (p instanceof Paintable)
        paint();
    else if  (p instanceof Tickable)
        tick();
}
(对象p:(ArrayList)world.getPaintables()的
{
if(可涂漆的p实例)
油漆();
else if(可勾选的p实例)
勾选();
}

我认为“修复”这一问题的最简单方法就是创建一个公共界面,并将其用于所有列表。如果您的所有类都实现了
Tickable
Paintable
,那么您可能无论如何都应该这样做

public class TickAndPaint
{
   public static void main(String[] args) {
      ArrayList<TickableAndPaintable> list = new ArrayList<>();
      for( Paintable t : list ) {
      }
      for( Tickable t : list ) {
      }
   }
}

interface Paintable {}
interface Tickable {}
interface TickableAndPaintable extends Paintable, Tickable {}
公共类TickAndPaint
{
公共静态void main(字符串[]args){
ArrayList=新建ArrayList();
用于(可绘制的t:列表){
}
for(可勾选的t:列表){
}
}
}
接口可绘制{}
接口可勾选{}
接口TickableAndPaintable扩展了Paintable,Tickable{}

返回world.getPaintables()的数据类型是什么? 如果该方法的返回值是Paintable的ArrayList,则不应强制转换任何内容。 无论如何,您可以做如下操作:

for(Object p : world.getPaintables()) {
    if(p instanceOf Paintable){
       (Paintable)p ... (do something);
    }
}

希望它能帮助你。

你根本不需要打字。在
World
上实现
Iterable
Iterable
,然后您可以简单地为(Paintable p:World)
或为(Tickable t:World)执行
操作,而无需进行类型转换。

一种不需要更改类/接口层次结构的替代方法,是在您的
世界
类中声明具有多个边界的
列表
容器。例如:

class World<T extends Object & Paintable & Tickable> {

    private List<T> tickablePaintables = new ArrayList<>();

    /*...*/

    public List<T> getTickablePaintables() {
        return tickablePaintables;
    }
    /*...*/       
}

由于Java中类型参数的工作方式,不幸的是,这会给类/方法声明(用于声明
T
)增加一些混乱。

最简单的事情可能是强制转换单个对象,而不是整个列表。它们必须有一个公共基类,然后您可以强制转换到该类。您应该先阅读本教程。@GergelyKőrössy它们都是不同超类的现成子类。@LouisWasserman我也这么想,但当我需要调用特定于接口的方法时,这会导致更深层次的问题。@Jarmund通常可以在不进行类型转换的情况下实现大部分内容。当您需要在某个对象中迭代某个对象时,对要迭代的每个类型使用
Iterable
接口,这样您就不需要类型转换了。请看下面我的答案。返回的所有对象都是可勾选和可绘制的,然后您应该按照marspace的建议执行操作!虽然有些臃肿,但这是迄今为止最干净的方法。谢谢
public <T extends Object & Paintable & Tickable> void doSomething() {

    World<T> w = new World<>();

    for (Tickable tickable : w.getTickablePaintables()) {
        //...
    }            
    for (Paintable paintable : w.getTickablePaintables()) {
        //...
    }            
}