0

I have 2 packages: controller and federation. Controller just contains controller class with main method, but federation contains 2 classes, Shuttle (parent class) and MiniShuttle (child class). Upcasting works like a charm, but when I try to downcasting, I get ClassCastException.

This is the code I tried:

Shuttle.java

package federation;

public class Shuttle {

    protected int passengers;

}

MiniShuttle.java

package federation;

public class MiniShuttle extends Shuttle {


}

Controller.java

package controller;

import federation.MiniShuttle;
import federation.Shuttle;

public class Controller {

    public static void main(String[] args) {
        Shuttle shuttle = new Shuttle();
        MiniShuttle mshuttle = (MiniShuttle)shuttle;

        if(mshuttle instanceof Shuttle)
        {
            System.out.println("ok");
        }else
        {
            System.out.println("not ok");
        }

    }

}
Amar Kalabić
  • 888
  • 4
  • 15
  • 33
  • 1
    What if Minishuttle added new instance fields or methods? And what if you tried to use them? You can't expect that a Parent class can behave the same as a child class of theirs. – Carcigenicate Oct 22 '18 at 15:04
  • @Carcigenicate Okay I get what's your point, but in which cases does downcasting work then? – Amar Kalabić Oct 22 '18 at 15:05
  • `shuttle` is not a `MiniShuttle`. What makes you think that such a cast would work? – Joe C Oct 22 '18 at 15:05
  • @AmarKalabić I don't think it ever works. I've never used it. I can't see why it would ever need to be used. If you think you need downcasting, you've probably set things up wrong and need to rethink your design. – Carcigenicate Oct 22 '18 at 15:08
  • You can't cast an object to a class it is not an instance of. A `new Shuttle` is not an instance of `MiniShuttle`, so you cannot cast it to one. – khelwood Oct 22 '18 at 15:08

4 Answers4

3

Because you have instantiated Shuttle. Declaration new Shuttle() says that object of type Shuttle is instantiated, and a reference to this object is Shuttle (from Shuttle shuttle = ...). If you want to get this to work, use Shuttle shuttle = new MiniShuttle(). With this you are actually saying "I'm instantiating an object of MiniShuttle type and upcasting a reference to it to the type of Shuttle".

nyarian
  • 4,085
  • 1
  • 19
  • 51
2

As you said, you are downcasting, meaning casting from a parent to a child - it won't work that way because shuttle is of type Shuttle and not MiniShuttle.

You could do it the other way though:

MiniShuttle miniShuttle = new MiniShuttle();
Shuttle shuttle = (Shuttle) miniShuttle;

That way you are upcasting and it is perfectly fine because each MiniShuttle is Shuttle as well.

syntagma
  • 23,346
  • 16
  • 78
  • 134
0

The contract in OOPS is defined by Super classes and not by sub classes. Basically the extends contract is defined as "is a" relationship where subclass is a object of Super class but not vice versa

Read it this way, MiniShuttle is a Shuttle but Shuttle is not a MiniShuttle

Arafat Nalkhande
  • 11,078
  • 9
  • 39
  • 63
0

You instantiated "shuttle" as a generic Shuttle object in line 1 of your main method, but then you tried to cast it to a MiniShuttle. You can't do that, because a Shuttle is not necessarily going to be a MiniShuttle, but something else. Here's another example that hopefully makes it clearer why that would be a bad assumption more concrete example illustrating why that's a bad assumption.

Shuttle ssQuark = new FerengiShuttle(); // a FerengiShuttle is also a Shuttle
MiniShuttle mshuttle = (MiniShuttle) ssQuark; // No!

A FerengiShuttle is a kind of shuttle, and mshuttle is also a shuttle, but ssQuark is not a MiniShuttle and was never intended to be. If you have a generic Shuttle object, you can't make the necessary assumptions required to downcast it.

Kazim
  • 99
  • 4