1

I was testing around with Java and noticed that casting "physically" changes properties of an object. I don't quite understand what actually happens inside Java when casting is used, but I did notice this:

Here is my Super class InstanceVariable:

package inheritance;

public class InstanceVariable {
    public int x = 1;
}

Here is a class that inherits from it:

package inheritance;

public class InstanceVariable1 extends InstanceVariable {

    public int x = 100;
    public static int y = 2;


    public static void main(String[] args) {
        InstanceVariable1 one = new InstanceVariable1();
        InstanceVariable two = new InstanceVariable1();
        System.out.println(one.x + " " + two.x);
        one = (InstanceVariable) one; //This is illegal
    }
}

First of all, the instance variable that were instantiated are overriden by the child class. And secondly, I can implicitly cast the super class (that is InstanceVariable) to two, but for some reason, I cannot explicitly cast it to one? What is the reason for this?

q.Then
  • 2,743
  • 1
  • 21
  • 31
  • 4
    Because one is _more_ than an InstanceVariable. – Thorbjørn Ravn Andersen Oct 27 '15 at 21:03
  • 1
    All figs are tree but all trees are not figs.. Think something on these lines – Kumar Abhinav Oct 27 '15 at 21:04
  • That explicit cast doesn't make any sense. You could do this, however: `InstanceVariable one = new InstanceVariable1();`. Your variable doesn't hold an InstanceVariable, it holds an InstanceVariable1 type. If you want any explanations to be more clear, you might want to use better class names. Your example is analagous to this: `ArrayList list = (List) new ArrayList();` – jgitter Oct 27 '15 at 21:04
  • What I mean is that, how is the implicit cast of `two` legal but the explicit cast of `one` is illegal? They are both `InstanceVariable1` objects – q.Then Oct 27 '15 at 21:06
  • The cast is OK but the assignment isn't. – Henry Oct 27 '15 at 21:06
  • On two, you are referring to the InstanceVariable1 class by its interface. That is perfectly rational. You aren't comparing apples to apples. – jgitter Oct 27 '15 at 21:08
  • Let's assume `InstanceVariable` = `Animal` and `InstanceVariable1` = `Dog` and then think about it: is every dog an animal? (e.g. `InstanceVariable two = new InstanceVariable1();`) And is every animal a dog? (e.g. `one = (InstanceVariable) one`) – Tom Oct 27 '15 at 21:09
  • Is it because the immutable nature of Java objects? as in I am trying to reassign and change the object into something else? In that case, what happens in the implicit cast case? – q.Then Oct 27 '15 at 21:10
  • Ok, but I'm wondering why the implicit cast is even allowed then – q.Then Oct 27 '15 at 21:10
  • Well, in the world where I came from i can say: every dog is also an animal ... ;). So why should that cast fail? – Tom Oct 27 '15 at 21:12
  • Ok, using the analogy `InstanceVariable` = `Animal` and `InstanceVariable1` = `Dog`, then `one` is assigned as a `Dog`. That makes sense, we cannot cast `Dog` to `Animal`. But for variable `two`, it is implicitly cast from a `Dog` to an `Animal`, and that case succeeds – q.Then Oct 27 '15 at 21:14
  • Again, there is nothing wrong with the cast. The problem is the assignment where you assign an `Animal` to a variable of type `Dog`. – Henry Oct 27 '15 at 21:15
  • @Henry, does the assignment fail for the same reason that: `int x = 1;` then: `x = "Hi";` fails – q.Then Oct 27 '15 at 21:17
  • *"That makes sense, we cannot cast Dog to Animal"* No, this is not correct. You _can_ cast a dog to an animal. But you can't cast an animal to a dog, because since it is an "animal" it could already be a `Cat` instance refered by that variable, so you would end up casting a cat to a dog. And yes, a "general" animal would fail as well. – Tom Oct 27 '15 at 21:18
  • Ok, but where am I casting a `Animal` to a `Dog`? – q.Then Oct 27 '15 at 21:19
  • You are not casting, you assign an `Animal` to a `Dog` variable. In this case a cast would even work because the object IS a `Dog`. e.g: `one = (InstanceVariable1)(InstanceVariable)one;` is OK. – Henry Oct 27 '15 at 21:21
  • This is ok as well: `two = (InstanceVariable)one;` – Henry Oct 27 '15 at 21:21

0 Answers0