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