views:

65

answers:

4

HI,

I have a down casting question, I am a bit rusty in this area. I have 2 clasess like this:

class A{ int i; String j ; //Getters and setters}
class B extends A{ String k; //getter and setter}

I have a method like this, in a Utility helper class:

public static A converts(C c){}

Where C are objects that are retireved from the database and then converted.

The problem is I want to call the above method by passing in a 'C' and getting back B. So I tried this:

B bClasss = (B) Utility.converts(c);

So even though the above method returns A I tried to downcast it to B, but I get a runtime ClassCastException. Is there really no way around this? DO I have to write a separate converts() method which returns a B class type?

If I declare my class B like:

class B { String k; A a;} // So instead of extending A it has-a A, getter and setters also

then I can call my existing method like this:

b.setA(Utility.converts(c) );

This way I can reuse the existing method, even though the extends relationship makes more sense. What should I do? Any help much appreciated. Thanks.

+2  A: 

What's important here is what Utility.converts() actually returns - if it doesn't create a new B object and return it, there's no way to get a B from it.

(since you're getting ClassCastException, then it doesn't create B inside)

Yoni Roit
Thanks Yoni, I have declared the method converts above as follows:public static A converts(C c){}so it does return A. I am wondering is there no other way around this issue, other than changing the relationship to has-a from is-a or writing another method?
msharma
it is not a problem with the declaration of converts(), it is a problem with the **implementation** of converts() (what does it do?)
Justin
+1  A: 

You should work in the appropriate level of abstraction and write your method signatures to do the same. If the public/default interface of B is modified that heavily from A, then your method signature really should be returning a B. Otherwise, ditch trying to cast it, assign the result of .converts to a variable of type A, and treat it like an A even though it's true type is really a B. You would be defeating the point of abstracting through inheritance if you are trying to downcast here.

Without seeing your source code, I have no clue whether or not it makes sense to use composition in lieu of inheritance here. The above paragraph assumes what you say about "extends relationship makes more sense" is really true.

whaley
+3  A: 

The cast from type A to type B:

B bClasss = (B) Utility.converts(c);

doesn't work because objects of type A don't have all the methods that might be called from references of type B. What would you expect to happen if you called

bClasss.getK();

on the next line? The underlying object has no member variable k, so this cast is not allowed.

You can use references of the higher types in your class hierarchy to refer to objects of lower types, but not the other way around.

Without knowing more, I think the best thing to do is implement multiple methods

A aObj = Utility.convertToA(c);
B bObj = Utility.convertToB(c);

If B extends A, then you should still benefit from some code reuse in the constructors of your classes.

Bill the Lizard
A: 

If your converts() method doesn't actually return a B, then there is no way to cast it to a B. Since you are getting a ClassCastException it clearly doesn't return a B.

You can of course write a converts(C c) that returns a B. But an alternative approach might be to write a constructor:

B(A a)

which creates a B based on the contents of A. Then you use converts to get a C, and create a B from it.

DJClayworth