简体   繁体   English

Java:如何将克隆的对象转换为它的原始子类?

[英]Java: How do I cast a cloned object to it's original subclass?

Imagine super class A:想象一下超A类:

public class A {
    private int x;

    A(int x){
        this.x = x;
    }

    public int getX() {
        return x;
    }
}

And it's 2 subclasses B and C:它是 2 个子类 B 和 C:

public class B extends A{
    private int y = 2;

    B(int x){
        super(x);
    }
}
public class C extends A{
    private int y = 3;

    B(int x){
        super(x);
    }
}

Now imagine a list of objects that all inherit class A. I want to iterate through that list and clone each object and also cast it to it's original subclass (B or C).现在想象一个所有继承类 A 的对象列表。我想遍历该列表并克隆每个对象并将其转换为它的原始子类(B 或 C)。 This is how I tried to do that:这就是我尝试这样做的方式:

public static void main(String args[]) {
    ArrayList<A> aList = new ArrayList<A>();
    aList.add(new B(5));
    aList.add(new C(6));

    ArrayList<A> aClones = new ArrayList<A>();

    for(A a : aList) {
        A aNew = new A(a.getX());
        a.getClass().cast(aNew);
        aClones.add(aNew);
    }
}

But this gives me an error saying that I can't cast A to B. How am I able to achieve this without knowing up front what subtype of object I'm dealing with?但这给了我一个错误,说我不能将 A 转换为 B。我如何在不知道我正在处理的对象子类型的情况下实现这一目标? I could do an if-statement inside the for loop for every type of subclass to check if a is an instance of that subclass and then simply create a new instance of that particular subclass and clone it that way.我可以在 for 循环中为每种类型的子类执行 if 语句以检查a是否是该子类的实例,然后简单地创建该特定子类的新实例并以这种方式克隆它。 However, in my situation there will be many more subclasses than just B and C and many more might come.但是,在我的情况下,将有更多的子类,而不仅仅是 B 和 C,而且可能还会有更多。 I don't want the for loop to contain any knowledge about the existing subclasses of A. Is this possible?我不希望 for 循环包含有关 A 的现有子类的任何知识。这可能吗?

You can do something like this你可以做这样的事情

for(A a : aList) {
    A anew;
    if (a.getClass() == A.class) anow = new A(a.getX());
    else if (a.getClass() == B.class) anow = new B(a.getX());
    else if (...

} }

This can't be done in the way you're writing it.这不能以您编写的方式完成。

The reason is fairly simple: B and C have an is-a relationship with A , but A doesn't share the same is-a relationship with either B or C .原因很简单: BCAis-a关系,但ABC不共享相同的is-a关系。

This is chiefly because you're trying to iterate using the superclass to describe everything.这主要是因为您正在尝试使用超类进行迭代来描述所有内容。

for(A a : aList) { }

While you're iterating, you do not have any way of knowing from type inference alone what concrete class A actually is.当您进行迭代时,您无法通过类型推断知道具体的类A究竟是什么。

So this fails, as expected.所以这失败了,正如预期的那样。

 a.getClass().cast(aNew);

Without explicitly asking the class what type it is , you have no way of doing this.如果不明确询问类它是什么类型,你就无法做到这一点。

This means that you'll be writing a lot of instanceof of statements if you plan to expand upon this.这意味着如果您打算对此进行扩展,您将编写大量的instanceof语句。

for(A a : aList) {
    if(a instanceof B) {
        B b = new B(a.getX());
        aClones.add(b);
    }
    if(a instanceof C) {
        C c = new C(a.getX());
        aClones.add(c);
    }
}

You should clone it with the constructor of the subclass.您应该使用子类的构造函数克隆它。 Otherwise it will be the Type of the super class A which cannot be casted to C or B See eg reflection: http://tutorials.jenkov.com/java-reflection/constructors.html否则它将是无法转换为 C 或 B 的超类 A 的类型参见例如反射: http : //tutorials.jenkov.com/java-reflection/constructors.html

Or better use the clone function.或者更好地使用克隆功能。 https://en.m.wikipedia.org/wiki/Clone_(Java_method) https://en.m.wikipedia.org/wiki/Clone_(Java_method)

That should be much easier.那应该容易多了。

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

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