Reputation: 434
Imagine super class 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:
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). 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? 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. However, in my situation there will be many more subclasses than just B and C and many more might come. I don't want the for loop to contain any knowledge about the existing subclasses of A. Is this possible?
Upvotes: 0
Views: 223
Reputation: 106400
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
.
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.
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.
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);
}
}
Upvotes: 1
Reputation: 358
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 e.g. reflection: http://tutorials.jenkov.com/java-reflection/constructors.html
Or better use the clone function. https://en.m.wikipedia.org/wiki/Clone_(Java_method)
That should be much easier.
Upvotes: 0
Reputation: 35011
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 (...
}
Upvotes: 1