First I define the superclass:
public class Living {
double energy;
Living(double energy) {
this.energy = energy;
}
}
Then I define the subclass:
public class Person extends Living {
String name;
Person(double energy, String name) {
super(energy);
this.name = name;
}
public String getName() {
return this.name;
}
public String toString() {
String s = this.getName() + " " + this.energy;
return s;
}
}
Now if I do this:
Living creature = new Person(15.2, "Joe");
I will have created a creature of type Living
by using the Person
constructor. This is allowed because Person
is a specialization of Living
.
However I still cannot access the methods of the Person
class - for example creature.getName()
- through the point operator, because creature is declared as of type Living
not Person
.
System.out.println(creature.getName()); //not possible
But if I do this:
System.out.println(creature.toString());
I get
Joe 15.2
So instead of the toString()
method of the Living
class (which is not overriden), the toString()
method of the Person
class is called. I am having trouble understanding why this is the case.
I declare in the beginning that creature should be of type Living
, although I use the Person
constructor. If creature does not have a name
attribute and its toString()
method is not overriden, how can I get the above output?
The object is indeed an instance of a Person
, and thus has all of the Person
methods. However, the reference is of the Living
type. The compiler does not know its runtime type, and only allows you to access methods it "knows" will be available - ie, the methods of the Living
type.
It could, however, be coerced to treat this variable as a Person
, but explicit casting:
System.out.println(((Person) creature).getName())
For every object, there is a table (virtual table) which keeps information about the methods defined for this object.
If a parent method is overridden in a given object, this table will store the address of the overridden method, even if the object is referenced as one of the parent class. Every time a method is called, this table is used to find out how to access that method.
Therefore, in your case it will use the redefined method toString, because it has replaced the parent method.
toString()
is declared in Object (from which all your classes inherit), that's why you can call it without being overridden in your class Living
(some goes for methods such as equals()
, hashCode()
, etc.).
Notice, that if you would call the toString()
on a different subclass of Living
, such as Animal
, which does not explicitly override toString()
, you would get a default toString()
result from Object
.
public class Animal extends Living {
String name;
Person(double energy, String name) {
super(energy);
this.name = name;
}
public String getName() {
return this.name;
}
// no toString override here
}
Calling toString()
on Animal
:
Living animal = new Animal(100, "Fido");
System.out.println(animal.toString()); // something like your.package.Animal@757dbeaf
That's one of the main characteristics of Object-oriented programming.
When you do Living creature = new Person(15.2, "Joe");
you are defining a variable which type is Living
, but as you stated, specialized as Person
. That means it won't have Person
methods, only its specializations!
So, for example, if Living
had a method
public String getName() {
return "foobar";
}
and you called creature.getName()
, the return would NOT be "foobar"
, but the "Joe"
instead. Because the 'specialization' of the method will be called, and not the super method itself.
However, only methods that are 'specialized' can be called: those who are particular to Person
or any other subclass can't.
The object is of type Person
, but the reference if of type Living
. As Living
doesn't declare a getName()
method, you get a compilation error, when you try to call it.
The toString()
method is actually declared in Object
, which is an implicit parent of Living
, so toString()
is declared. As the object is of type Person
, and it overrides toString()
, it is the one called.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.