0

Everything occurs in Java. I'm not sure to what extent the programming language affects my questions, and I would be interested to know.

Suppose I have a class Animal, and a subclass which extends Animal called Dog. My understanding is that writing

Animal dog1 = new Dog();

constructs an object Dog called dog1 of type Animal. If I now write

Dog dog2 = new Dog();

then this constructs an object Dog called dog2 of type Dog. Suppose now I upcast the type of dog2 to type Animal. Then I lose access to all methods in Dog which are not overrides of methods in methods in Animal (otherwise, the corresponding methods in Dog are called).

Now suppose I add interfaces into the above story. From what I've read, every object has exactly one class-type (e.g. in the above, dog1 is type Animal, and dog2 is type Dog pre-upcast). However, objects have (not can have, but have) multiple interface-types, one for each interface the class implements. Suppose the class Dog implements the interface isCute, and suppose the class Animal implements the interface isLiving. In this case, I have the following questions.

  1. Is the type of dog1 both Animal and isLiving?
  2. Is the type of dog2 both Dog and isCute? Or is the type of dog2 Dog, isCute, and isLiving?
  3. If I upcast dog2 to Animal, is the type of dog2 Animal and isLiving?

I have tried searching, but I don't see answers covering discussing this relationship in too much depth. Most answers resort to "don't use upcasting" which is not an answer I am looking for.

Mr. Brown
  • 111
  • 6
  • You can easily experiment and see what the Java compiler tells you. – tgdavies Jul 24 '23 at 21:55
  • Write `IsLiving x = dog1;` and see if it compiles. – tgdavies Jul 24 '23 at 21:57
  • Also try `dog1.getClass()`. – shmosel Jul 24 '23 at 21:58
  • 2
    And remember that in both your scenarios, exactly the same object is created: an object of class `Dog`. It's just the reference which has a different type, which just affects what the compiler will allow you to do with it. It has no effect on the actual object. – tgdavies Jul 24 '23 at 21:58
  • 1
    `If I upcast dog2 to Animal, is the type of dog2 Animal and isLiving?` Well, it's type was `Animal` and `isLiving` before, because Dogs are also Animals and also isLiving. tgdavies point is a good one, the *object* doesn't change in Java (note that primitives will actually change time when cast though). The compiler will tread your cast as if the object is Animal and isLiving, but you could still cast back to `Dog` successfully, because the object itself is still a Dog. – markspace Jul 24 '23 at 22:03
  • 2
    Does this answer your question? [java do extended classes have two types](https://stackoverflow.com/questions/76741198/java-do-extended-classes-have-two-types). The answer in this thread is I believe a very good explanation of the scenario in non-technical terms. – Mushroomator Jul 24 '23 at 22:04
  • 1
    don't mix the type of the variable (compile time) and the type of the instance (runtime) referenced by that variable - the variable `dog1` is of type `Animal`, but the instance it references is still a `Dog` - you can do `Dog dog = (Dog) dog1` without getting an error (would fail at runtime, if it was a `Cat`) – user16320675 Jul 24 '23 at 22:21
  • Ok I see the in the two instances the variable types are identical but the reference types are what changes with upcasting. However, it’s also true (I’ve tested) that you lose access to Dog methods (which are not overrides of animal methods) if the reference type is Animal. – Mr. Brown Jul 24 '23 at 22:36
  • So is it true that objects have multiple types while there is at most one reference type? If so, must the reference type also be a class-type? – Mr. Brown Jul 24 '23 at 22:44
  • “the variable types are identical” that’s not quite right. The types of the variables are the reference types. The types of the objects that those variables reference are identical. `Animal dog1 = new Dog()` does two things: 1. Creates a new object of type `Dog`, 2. Assigns a reference to that object to a variable of type `Animal`. – Tim Moore Jul 24 '23 at 23:25
  • Sorry, you’re right. I meant to say the objects have identical type. – Mr. Brown Jul 24 '23 at 23:31
  • “So is it true that objects have multiple types while there is at most one reference type?” I wouldn’t put it that way. Objects and references each have a single main type, but types are arranged in a hierarchical relationship such that having one type can also imply having other types as well. Consider real world analogies: every dog _is_ an animal. Putting it on a list of various animals that includes cats and hamsters doesn’t make it any less of a dog. – Tim Moore Jul 24 '23 at 23:40
  • I understand this for object-types. But if your analogy held for reference-types then I don’t see the point of up/down casting. I thought the point of casting is exactly to change the reference-type. – Mr. Brown Jul 24 '23 at 23:45
  • Casting converts a reference from one type to another, but does not change the original reference. The code `(Dog) dog1` doesn’t change the type of `dog1` from `Animal`, but the type of the resulting expression is `Dog` and therefore can be assigned to a variable of type `Dog`. – Tim Moore Jul 25 '23 at 01:36

1 Answers1

0

I’ll update this with corrections if needed. Thanks to the comments, one big clarification is the difference between object types and reference types. As far as I can tell, objects have as many types as there are classes they (maybe implicitly) extend and instances they implement. There is at most one reference type, and this is always a class-type (is this true?)

So to answer my original question: all instances have the same object type, namely Animal, Dog, isCute and isLiving, among others.

  1. The reference type is Animal.
  2. The reference type is Dog.
  3. The reference type is Animal.
Mr. Brown
  • 111
  • 6