Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 扩展泛型类时的ClassCastException_Java_Arrays_Generics_Libgdx - Fatal编程技术网

Java 扩展泛型类时的ClassCastException

Java 扩展泛型类时的ClassCastException,java,arrays,generics,libgdx,Java,Arrays,Generics,Libgdx,假设我有一个类Text,它实现了一个名为Drawable的接口,定义如下: public interface Drawable { public void draw (DrawConfig drawConfig); } 我希望有一个对象,它的行为类似于一个包含项的数组,但也实现了Drawable,能够编写drawables.draw(drawConfig),并让它将调用转发给它的所有子级,而不必执行for循环。因此,我首先创建了一个包装器类,如下所示: public class Draw

假设我有一个类
Text
,它实现了一个名为
Drawable
的接口,定义如下:

public interface Drawable {

  public void draw (DrawConfig drawConfig);
}
我希望有一个对象,它的行为类似于一个包含项的数组,但也实现了
Drawable
,能够编写
drawables.draw(drawConfig)
,并让它将调用转发给它的所有子级,而不必执行for循环。因此,我首先创建了一个包装器类,如下所示:

public class Drawables implements Drawable {

  private final Array<Drawable> items = new Array<Drawable>();

  public void add (final Drawable value) {
    this.items.add(value);
  }

  @Override
  public void draw (final DrawConfig drawConfig) {
    for (final T item : this.items)
      item.draw(drawConfig);
  }
}
这意味着我必须制作另一个数组,最后我会得到两个数组。我想避免这种情况,所以我考虑使用泛型,因为
Array
类是泛型的,我将
Drawables
类转换为:

public class Drawables<T extends Drawable> extends Array<T> implements Drawable {

  @Override
  public void draw (final DrawConfig drawConfig) {
    for (final T item : this.items) // Line 17
      item.draw(drawConfig);
  }
}
请参见代码第17行的注释


有什么问题?甚至可以实现我想做的事情吗?

擦除后的问题:

for (final Drawable item : this.items) // this.items is of Object[]!!!
现在for循环不知道如何强制转换(java中没有隐式强制转换)。无法简单地编写
Drawable item=new Object()。你必须自己做演员:

for (Object o : this.items) {
  Drawable item = (Drawable) o;
  item.draw(drawConfig);
}

相关:

我认为你的设计不对。与其将绘制单个项目和绘制多个项目分开,
Drawable
只应在其合同中指定它根据某些配置绘制。它如何做到这一点,或者它使用什么其他对象来实现这一点,并不重要

因此,我首先要做的是:

public interface Drawable {
    void draw (DrawConfig drawConfig);    
}
现在,您似乎希望您的
Drawable
维护一个私有成员。这个私人成员对事物的绘制有一定的影响。有趣的是,它可能是正在绘制的对象本身,或者它可能包含需要绘制的对象,或者它可能是完全其他的对象。我们现在还不知道它会如何影响
draw
的行为。那我们怎么处理呢?我们可以创建一个抽象类来维护这个私有成员,并实现
Drawable

public abstract class AbstractDrawable<T> implements Drawable {    
    protected T data;           
}
这里我们有一个非常具体的
AbstractDrawable
实现,它本身可以与一个Drawable列表一起工作。这个具体的实现定义了它如何管理状态(它使用内部的
Drawable
实例列表)以及它如何管理行为(它的“draw”行为是“绘制”它维护的每个
Drawable
实例)

您提到您需要所有列表方法,等等。仅仅为了访问其方法而扩展类不是一个好主意。您的可绘制项目列表实际上不是一个列表。它是一个可绘制文件,恰好与可绘制文件列表一起使用。上面的方法隐式地使用组合而不是继承,因为
AbstractDrawable
封装了一些将以某种方式绘制的内部数据(不重要的是如何绘制;只是如何绘制)。因此,您现在可以维护一个内部列表,然后以您选择的方式“绘制”,而不是扩展
列表。这正是具体实现
Drawables
中发生的情况


您的下一个问题是无法在
Text
实例上调用
t.setText()
。唯一可以这样做的方法是,如果您有一个具体的实例专门用于
Text
实例,或者如果您在
draw
中执行了
instanceof
检查。这是因为您所拥有的是
T扩展可绘制的
;类知道它是某种
可绘制的
,并且它能够
绘制
。除此之外,它不知道具体的实现。

类数组实现Iterable。所以你可以这样写

@Override
public void draw (final DrawConfig drawConfig) {
  for (final T item : this) // Line 17
      item.draw(drawConfig);
}

什么是
数组
?它不是内置的
数组
类。@markspace@LucasRoss,但它的行为可以像一个。这都是一种接口状态。我不能100%确定自定义
Array
类是如何工作的,但是在这个StackOverflow问题中有一些关于处理数组和泛型的信息:转换每个项不是很昂贵吗?当我扩展
Array
时,我不明白当我实例化它时,为什么它会被视为
对象的数组而不是
文本的数组。@Defiryte,检查您是否想了解擦除以及需要擦除的原因。要使其正常工作,必须将
AbstractDrawable
声明为抽象,并且必须将
数据
声明为受保护。此外,我尝试了您的代码,但无法实例化
Drawables
类,因为当我为类型t传递给它时,我有一个错误。@failyte编辑了输入错误。您永远不会直接实例化
可绘制的
。我假设你有像
Text
这样的东西,它实现了
Drawable
。因此,您将要创建的是
Drawables
的一个实例。你也可以创建一个
Drawables
的实例,并给它任何实现
Drawable
的东西。是的,现在编辑你的帖子,我可以做
Drawables-Drawables=new-Drawables()
,但我有两个问题:1)我仍然需要手动添加
add()
remove()
方法等,以
AbstractDrawable
和2)我不能再循环我的
drawables
对象,因为它不可
Iterable
。我不认为这些是问题。您必须考虑如何使用
Drawables
对象。你是更关心它里面的东西被画出来,还是你关心这些东西本身?包含
添加
删除
,然后将其委托给内部列表并不需要太多工作。如果您真的想要访问Drawable列表,可以添加一个返回内部实例的方法。但我不明白为什么不能维护一个外部列表,然后只向
可绘制文件提供元素。尽量不要把太多的责任分配给一个班级(SRP)。
public interface Drawable {
    void draw (DrawConfig drawConfig);    
}
public abstract class AbstractDrawable<T> implements Drawable {    
    protected T data;           
}
public class Drawables<T extends Drawable> extends AbstractDrawable<List<T>> {

    public Drawables() {
        this.data = new ArrayList<T>();
    }

    public void addDrawable(T item) {
        this.data.add(item);
    }

    @Override
    public void draw (final DrawConfig drawConfig) {
        for (final T item : this.data) {
            item.draw(drawConfig);
        }
    }
}
@Override
public void draw (final DrawConfig drawConfig) {
  for (final T item : this) // Line 17
      item.draw(drawConfig);
}