Spaces:
Running
Running
| Let's also examine a situation where a METHOD is OVERRIDDEN in a subclass. | |
| In the class "Lorry", the method getCapacity has been IMPLEMENTED AGAIN: | |
| class Truck { | |
| private int capacity; | |
| public Truck(int capacity) { | |
| this.capacity = capacity; | |
| } | |
| public int getCapacity() { | |
| return this.capacity; | |
| } | |
| } | |
| class Lorry extends Truck { | |
| private int trailerCapacity; | |
| public Lorry(int capacity, int trailerCapacity) { | |
| super(capacity); | |
| this.trailerCapacity = trailerCapacity; | |
| } | |
| // HERE | |
| @Override | |
| public int getCapacity() { | |
| return super.getCapacity() + trailerCapacity; | |
| } | |
| } | |
| Let's create a new object of type "Lorry", and save the reference to a "Truck"-type variable. | |
| The type of the variable defines the operations that can be used: | |
| thus, we can only call methods defined in the "Truck" class. | |
| So let's call the "getCapacity" method, which is defined in the "Truck" class and overridden in the "Lorry" class. | |
| public class LorryTest { | |
| public static void main(String[] args) { | |
| //INITIALISE 'Lorry' object as a 'Truck' / superclass | |
| Truck vehicle = new Lorry(10, 20); | |
| System.out.println("Capacity: " + vehicle.getCapacity()); | |
| } | |
| } | |
| The program outputs | |
| Capacity: 30 | |
| From this example, we notice that the method call is directed to the implementation given in the Lorry class, even though the type of the variable is Truck. | |
| As a general rule, | |
| - The VARIABLE TYPE DETERMINES the AVAILABLE OPERATIONS / METHODS | |
| - The OBJECT TYPE determines the IMPLEMENTATIONS used by the METHODS | |
| This is called dynamic binding: Java always looks for the LATEST IMPLEMENTATION of each METHOD. | |
| https://docs [dot] google [dot] com/presentation/d/e/2PACX-1vTpe_7VNECaErEVyCbdD2Ud_CcEaS7sDoG7YD5ic--v34mX0QCzEZRQ-q-ENqkjTI6wiGT-Kh0rHNPl/embed?start=false&loop=false&slide=id.p | |
| ========================================== | |
| Note that dynamic binding works in the same way also with internal calls of an object. | |
| Let's look at a situation where the class 'DetectiveNovel' inherits from the class 'Book'. | |
| In the "DetectiveNovel" class, the 'getTitle' method is overridden, but not the toString method. | |
| class Book{ | |
| public String getTitle(){ | |
| return "book - "; | |
| } | |
| public String getPublisher(){ | |
| return "publisher"; | |
| } | |
| public String toString(){ | |
| return getTitle() + getPublisher(); | |
| } | |
| } | |
| class DetectiveNovel extends Book { | |
| @Override | |
| public String getTitle() { | |
| return "detective novel - "; | |
| } | |
| } | |
| When the "toString" method is called for a "DetectiveNovel"-type object, | |
| it always uses the "DetectiveNovel" class implementation for the "getTitle" method: | |
| public class DetectiveNovelTest { | |
| public static void main(String[] args) { | |
| Book book = new DetectiveNovel(); | |
| System.out.println(book.toString()); | |
| } | |
| } | |
| // 'Book' toString() | |
| // IMPLEMENTs getTitle() + getPublisher() | |
| // ie 'DetectiveNovel'/OVERRIDDEN getTitle() + 'Book'/ORIGINAL getPublisher() | |
| The program outputs: | |
| detective novel - publisher | |
| ========================================== | |
| Determining the Type of an Object | |
| As the TYPE of an OBJECT DETERMINES the outcome of a METHOD CALL in some situations, | |
| we need to be able to determine the type. | |
| This is done, for instance, with the operator 'instanceof'. | |
| The operator returns the value true, if the given object is of the given class type, i.e. | |
| A instanceof B | |
| obj1 instanceof Class1 | |
| variable1 instanceof Class1 | |
| returns the value true if A's type is B. | |
| An example clarifies the situation: | |
| public static void main(String[] args) { | |
| Person ollie = new Student("Oliver", "12345", 123); | |
| System.out.println(ollie instanceof Student); | |
| System.out.println(ollie instanceof Person); | |
| System.out.println(ollie instanceof Object); | |
| System.out.println(ollie instanceof Teacher); | |
| } | |
| The Program outputs: | |
| true | |
| true | |
| true | |
| false | |
| So, a "Student" type is both a "Student", "Person" and "Object". | |
| In fact, the statement | |
| A instanceof Object | |
| is true for all Java objects, as "Object" is the superclass of all classes. | |
| If there is a need TO DETERMINE the "ACTUAL" TYPE of an OBJECT and the type of the superclass is not sufficient, | |
| we can use the method "getClass": | |
| public static void main(String[] args) { | |
| Person oliver = new Student("Oliver", "12345", 123); | |
| System.out.println("Oliver is a Person: " + (oliver instanceof Person)); | |
| System.out.println("Oliveris a Person: " + (oliver.getClass() == Person.class)); | |
| System.out.println("Oliver is a Student: " + (oliver instanceof Student)); | |
| System.out.println("Oliver is a Student: " + (oliver.getClass() == Student.class)); | |
| } | |
| Ohjelma tulostaa: | |
| Oliver is a Person: true // 'Student' object type is a subclass of 'Person' | |
| Oliver is a Person: false // 'Student' object type was not initialised as a 'Person' class | |
| Oliver is a Student: true // 'Student' object type | |
| Oliver is a Student: true // 'Student' object type was initialised as a 'Student' class | |
| ==================== | |
| A typical example is the "equals" method, | |
| where it is determined whether an object is of the same type as the object being compared | |
| - see an example by generating the "equals" method in Eclipse! | |
| Let's consider an example of a method that receives a list of "Person"-class type objects | |
| and prints information about each object, | |
| whether it is a "Person", "Student" or "Teacher" object: | |
| // VARIABLE TYPE = 'Person' | |
| // OBJECT TYPE => depends on HOW OBJECTS WERE INITIALISED | |
| public static void whatType(ArrayList<Person> people) { | |
| for (Person person : people) { | |
| if (person.getClass() == Person.class) { | |
| System.out.println("This is a person!"); | |
| } | |
| else if (person.getClass() == Student.class) { | |
| System.out.println("This is a student!"); | |
| } | |
| else if (person.getClass() == Teacher.class) { | |
| System.out.println("This is a teacher!"); | |
| } | |
| } | |
| } | |