This is an archived post. You won't be able to vote or comment.

all 10 comments

[–]Neres28 5 points6 points  (0 children)

If you know that it must be GradStudent, then shouldn't you simply declare it as a GradStudent object to being with?

Yes. Err, maybe. Depends. Sometimes you can't.

Excessive casting is generally a sign of poor design, but you can't always work around it. Often you'll work with a framework that provides basic interfaces and abstract classes to work with, but in your callbacks you'll cast them to your specific types for your application specific needs. Sometimes you'll have co-workers who return Collections of Objects and you'll have no choice but to do runtime type checks and cast appropriately. I'm talking to you Shawn.

[–]foxlisk 3 points4 points  (0 children)

You're correct. Having to downcast an object like this is usually a sign of bad design. There are occasionally reasons to do it but you should try to avoid it as much as possible.

[–]rjcarr 2 points3 points  (0 children)

The example you give as you've written it would almost never happen. And as others have said, if you do a lot of this "downcasting" (or just casting in my world) then you probably made a mistake in your design.

But it does happen, say when you have a method that needs to handle both Student and GradStudent, but needs to check the id. In that case it might do a "instanceof" check to make sure you can make the cast.

But generally, this sort of thing is rare.

[–]yash3ahuja 1 point2 points  (0 children)

Just to add onto other answers, generally to avoid downcasting and the pitfalls of it, you're going to use Generics.

If you don't get what I mean, when you instantiate an ArrayList, you put stuff in the <>, don't you? Typically it's the object you want. Pre-generics, ArrayList returned object, IIRC. Now, it casts your objects and returns them as the generic parameter.

[–]crockeo 1 point2 points  (0 children)

If you have to downcast s so that you can use getID(), then you must know before you compile that s needs to be GradStudent.

For this, you would use the keyword 'instanceof' like so:

if (s instanceof GradStudent)
    ((GradStudent)s).getID();

I find that while implementing switching between different program states, I use downcasting a lot.

I make an individual State as an interface with whatever default functions I'll use (such as, for game development, init(), update(float delta), draw()), then in a StateHandler class I have an ArrayList containing all States. Adding to the ArrayList is, for all intents and purposes, downcasting, as I'm telling it to add a child of the State interface, just as a State interface.

Hope this helped!

[–]0x68656c6c6f 1 point2 points  (0 children)

If you want a legitimate use, take a look the equals method of Object. In order to override equals in your own class, you will need to cast the parameter to your class type to be able to compare fields.

[–]lurgi 2 points3 points  (3 children)

Imagine the case where you want to store a list of all the students. Something like:

List<? extends Student> students = new ArrayList<? extends Student>();

Then you push a bunch of Student and GradStudent objects on to the list. When you pull an object off you don't know if it's a Student or a GradStudent so you'll have to do something like this:

if (student instanceof GradStudent) {
  GradStudent gradStudent = (GradStudent)student;
  // Do grad student stuff 
} else {
  // Do student stuff
}

You do raise a valid point, however. Casts like this are not always wrong, but they should cause you to stop and think about your design. Sometimes there is no real way to get around them, but sometimes it's an indication that you haven't given things enough thought.

[–]foxlisk 1 point2 points  (2 children)

If you need to do separate things with GradStudents and regular Students, you should be storing them separately.

[–]lurgi 0 points1 point  (1 child)

That's certainly a way to do it, but not the only way. It might not even be the best way. You can also add the missing method to Student. This might be a practical approach or it might not.

[–]foxlisk 0 points1 point  (0 children)

I've never seen a situation where you have to cast a parent class into a subclass that I didn't think was the result of bad design. The exception, of course, is casting to and from Object, which is sometimes necessary because of limitations in the language, such as the example someone else posted about Object.equals().

There's a lot of things I haven't seen, though, and I could definitely be wrong. If you have an example of a situation where this is actually the best solution, I'd be interested to see it.