How does Object.toString() work for different underlying types?
Asked Answered
S

5

7

I don't understand why this works in java:

If I have an Integer object in a object, example:

Object myIntObj = new Integer(5);

Now if i do:

System.out.println(myIntObj);

the output is: 5

I now that the Integer class has an ovveride of the toString method but in this case is different (I think). For the polymorphism, if I have a "child object" in a "father variable" the object doesn't change its real type (in this case Integer) But... it (in the Object variable) can just use the method of the Object Class, so why if I write:

System.out.println(myIntObj);

I can see directly the number 5 and not the reference of this object? Because toString method in the object class by default return just a string of the reference of the object.

like:

Object currentPlayer = new Player();
System.out.println(currentPlayer);

In this case the output is the reference of the Player objecet because is called the toString method in the object class.

So why in the example of before I don't see the reference but directly the number? by logic, the rules of the polymorphism says that: if u have a "child" object in a "father" variable, this object, inside, remanis the same but he is used like an istance of object, so he can just uses the class object and so just the method of object, so is really strange that I don't see the reference but directly the number.

I hope you understand what I mean.

Stefa answered 23/11, 2013 at 2:29 Comment(2)
Is toString() defined for the Player class?Perichondrium
Just a comment. The characters you see when you output an object to console isn't a reference as such but the hashcode.Wilen
A
4

Your last paragraph where you explain your reasoning is slightly incorrect.

so why in the example of before i don't see the reference but directly the number? by logic, the rules of the polymorphism says that: if u have a "child" object in a "father" variable, this object, inside, remanis the same but he is used like an istance of object, so he can just uses the class object and so just the method of object, so is really strange that i don't see the reference but directly the number.

The beginning is correct, but the part I bolded is an incorrect conclusion you drew from it.

You are correct that with polymorphism, the object truly remains whatever type it is, but the reference type (the type of the variable) defines what you can do with it. However, the reference type does not describe what the object does

That is the intent behind polymorphism. It is an abstraction to define what can be done separately from how it works. For example, if you have this example:

public class Vehicle {
    public int getWheelCount() {
        return 1;
    }
}

public class Car extends Parent {
    public int getWheelCount() {
        return 4;
    }

    public void blowHorn() {
        System.out.println("Honk honk!");
    }
}

public class Bicycle extends Parent {
    public int getWheelCount() {
        return 2;
    }
}

Car car = new Car();
car.getWheelCount();  // 4
car.blowHorn();  //"Honk honk!"

Vehicle v = new Car();
v.getWheelCount()  // 4
v.blowHorn();  // COMPILE ERROR HERE!  Unknown method

Bicycle b = new Bicycle();
b.getWheelCount();  // 2

Vehicle v = new Bicycle();
v.getWheelCount();  // 2

What you can conclude from this is that when over-riding a method in a sub-class, the child version is always called. A car is always a car whether you are referring to it as a vehicle or as a car. But by referring to it as a vehicle, you are limited to invoking methods which are defined on all vehicles.

To tie it to the example, all Vehicle objects have a wheel size, therefore getWheelCount() is always callable whether it's Vehicle.getWheelCount() or Car.getWheelCount(). However, Car.getWheelCount() is what executes because Car over-rides it.

If the reference type is Vehicle, you cannot call blowHorn() because that method is only available on Car.

Going back to your example, an Integer is an Integer.

Object i = new Integer(5);
i.toString();  // 5

This prints 5 because i is an integer. The Integer class over-rides toString. The reference type (the type you are referring to the object as) only determines which methods you can call, but not which parent/child class's version of the method is called.

Algometer answered 23/11, 2013 at 2:58 Comment(1)
thank you so much, i'm programming since 2 years and in this situation everytime i did a cast because i didint know that was possibile when u have a child object in a father variabile to jump in the child class to call the method. i thought that in this case the child class was completely forget, so every time i did ((Integer)i).toString();Stefa
V
3

By defining it as Object this means you will only have access to methods that are defined in the Object class.

This includes toString().

So when you instantiate new Player() you still only have access to the methods from Object, but if you override this (like Integer.toString() does), you will still have the output as defined in the instantiated class.

PS: Father -> Parent

Vowelize answered 23/11, 2013 at 2:33 Comment(0)
B
2

This is how the concept of overriding methods works: once an object somewhere in the inheritance hierarchy provides an implementation, it is this implementation that is going to be called, unless it is overridden by another class further down the inheritance hierarchy.

Since java.lang.Integer provides an override of toString(), this override is called instead of the implementation provided by the java.lang.Object.

There is no difference between System.out.println(myIntObj) and System.out.println(myIntObj.toString()), because println will call toString internally on all objects which it does not know how to print.

The reason your Player class behaves differently is that it does not override toString(). If it did, you would see its results printed. With no override, however, the default implementation provided by java.lang.Object is called, which prints some generic object info.

Brigid answered 23/11, 2013 at 2:36 Comment(0)
K
1
Object myIntObj = new Integer(5);

Here you're creating a new Integer instance, not a bare Object instance. The fact that you're assigning it to an Object reference doesn't transform it into a bare Object. It's still an Integer, but you can reference it as an Object because it extends Object. So when you call myIntObj.toString(), you're calling that instance's toString() method. That instance turns out to be an Integer instance. And so Integer.toString() is called.


Object currentPlayer = new Player();

In this case the same rules apply when calling currentPlayer.toString(): you're actually calling Player.toString(). If Player class does not override toString(), then first ascending parent class toString() implementation is called. If Player directly extends Object, then Object.toString() is called, but if for example Player extends Human and Human extends Object, then Human.toString() is going to be called if it exists. If not, then Object.toString().

Knotgrass answered 23/11, 2013 at 2:35 Comment(0)
H
0

Consider this case where Employee has a subclass Manager that has a method getDetails() overridden,

Employee e=new Employee();
Employee m=new Manager();

If you invoke e.getDetails() you will get the behavior associated with Employee.

If you invoke m.getDetails() you will get the behavior associated with Manager.

In general, you get the behavior associated with the object to which the variable refers at runtime. This behavior is often referred to as virtual method invocation.

So the reason why you are getting the behavior associated with Integer when your reference is an object is because you are referring to an Integer object at runtime.

Halleyhalli answered 23/11, 2013 at 2:50 Comment(1)
thanks, but why if i do m.aMethodofManagerClass() eclipse says to me "Ehy you cannot!, in Employee this method doesnt exists!" if you are right, and i try to compile, it have to works! because at runtime in the Employee variable (m), i have Manager.aMethodOfManagerClass() so it have to works, but not. it doesntStefa

© 2022 - 2024 — McMap. All rights reserved.