Abstract Classes and Polymorphism CSC 123 Fall 2018 Howard Rosenthal
Lesson Goals Define and discuss abstract classes Define and discuss abstract methods Introduce polymorphism Much of the information in this section is adapted from: http://www.programmedlessons.org/java9/index.html Java Illuminated 5 TH Edition, Anderson, Julie and Franceschi Herve, Jones and Bartlett, 2019 Starting Out With Objects From Control Structures Through Objects, Gaddis, Tony, Pearson Publishing, 2016 2
What Is An Abstract Class In the last section we learned that classes in a hierarchy are related by the is-a relationship. For example, a Nissan is-a Automobile, and a Sentra is-a Nissan. Java has features that allow programs to establish and work with hierarchies. Much of the power of object oriented programming comes from this. An abstract class is a class that cannot be instantiated but that can be the parent of other classes. This is useful when you have a broad concept (like Automobile) but actual objects must be specific types (like Sentra). In this lesson we will look at a hierarchy of cards 3
A Sample Card Hierarchy 4
Abstract Classes An abstract class in Java is a class that is never instantiated. Its purpose is to be a parent to several related classes. The children classes inherit from the abstract parent class. It is defined like this: abstract class ClassName {..... // definitions of methods and variables } Access modifiers such as public can be placed before abstract. Even though it can not be instantiated, an abstract class defines methods and variables that children classes inherit, as we will shortly describe 5
Abstract Methods An abstract method has no body. It declares an access modifier, return type, and method signature followed by a semicolon. It has no statements. A non-abstract child class inherits the abstract method and must define a non-abstract method that matches the abstract method. Abstract classes can (but don't have to) contain abstract methods. Also, an abstract class can contain non-abstract methods, which will be inherited by the children. An abstract child of an abstract parent does not have to define non-abstract methods for the abstract signatures it inherits. This means that there may be several steps between an abstract base class to a child class that is completely non-abstract. (You don t need to define each method the first step down. 6
Defining An Abstract Method To declare a method as abstract, include the abstract keyword in the method header, and end the header with a semicolon: accessmodifier abstract returntype methodname( argument list ); Note: The semicolon at the end of the header indicates that the method has no code. We do not use opening and closing curly braces.{ 7
Method Signature Quick Reminder: A signature looks like this: somemethod( int, double, String ) The return type is not part of the signature. The names of the parameters do not matter, just their types. The name of a method is not enough to uniquely identify it. There may be several versions of a method, each with different parameters. The types in the parameter are needed to specify which method you want. 8
The Structure Of An Abstract Class A simple framework for abstraction. Note that the method has no body abstract class Card { protected String recipient; // name of who gets the card public abstract void greeting(); // abstract greeting() method - There is no body } Since no constructor is defined in Card the default noargument constructor is automatically supplied by the compiler. However, this constructor cannot be used directly because no Card object can be constructed. Why? Because abstract classes can t be used to create objects. 9
Extending An Abstract Class (1) Below is an example that extends Card class Holiday extends Card { public Holiday( String r ) { recipient = r; // recipient in Card is protected, so this works } public void greeting() { System.out.printf("Dear %s\n", recipient); System.out.printf("Season's Greetings!\n"); } } 10
Extending An Abstract Class (2) The class Holiday is not an abstract class. Objects can be instantiated from it. Its constructor implicitly calls the no-argument constructor in its parent, Card, which calls the constructor in Object. So even though it has an abstract parent, a Holiday object is just as much an object as any other. Notes: Holiday inherits the abstract method greeting() from its parent. Holiday must define a greeting() method that includes a method body (statements between braces). The definition of greeting() must match the signature given in the parent. If Holiday did not define greeting(), then Holiday must be declared to be an abstract class. This would make it an abstract child of an abstract parent. 11
Abstract Classes Can Have Non-Abstract Methods Not everything defined in an abstract classes must be abstract. The variable recipient is defined in Card and inherited in the usual way. However, if a class contains even one abstract method, then the class itself has to be declared to be abstract. See Card.java, Holiday.java and CardTester.java for a very simple example 12
Why Use Abstract Classes Abstract classes are used to organize programs. Of course the same program can be organized in many ways. Our example program could be written without an abstract class. But a real-world application might have hundreds of classes. Grouping classes together is important in keeping a program organized and understandable. The advantage of using an abstract class is that you can group several related classes together as siblings. The picture shows this program after its object has been constructed. Look at CardTesterV2.java to see how we can instantiate a Holiday Card with different greetings 13
Multiple Classes From A Single Abstraction We can create multiple classes from a single abstraction, and then create objects from any of those classes See Holiday.java, Valentine.java, Birthday.java and CardTesterV3.java Remember You can t instantiate an object from an abstract class 14
Summary Of Abstract Classes An abstract class is intended to be extended but not instantiated. Usually (but not required), the abstract class contains one or more abstract methods. An abstract method specifies an API but does not provide an implementation. The abstract method is used as a pattern for a method the subclasses should implement. An abstract class cannot be used to instantiate objects. However, an object reference to an abstract class can be declared. We use this capability in polymorphism, discussed later. An abstract class can be extended. Subclasses can complete the implementation. Objects of those subclasses can be instantiated. 15
Restriction When Defining Abstract Methods An abstract method definition consists of: optional access modifier (public, private, and others), the reserved word abstract, the type of the return value, a method signature, a semi-colon. no braces for a body abstract methods can be declared only within an abstract class. An abstract method must consist of a method header followed by a semicolon. abstract methods cannot be called. abstract methods cannot be declared as private or static. A constructor cannot be declared abstract. 16
17
What Is Polymorphism? An important concept in inheritance is that an object of a subclass is also an object of any of its superclasses. That concept is the basis for an important OOP feature called polymorphism. Polymorphism means "having many forms." In Java, it means that one variable might be used with several objects of related classes at different times in a program. Polymorphism simplifies the processing of various objects in the same class hierarchy because we can use the same method call for any object in the hierarchy using a superclass object reference. 18
Using Polymorphism To use polymorphism, these conditions must be true: The classes are in the same hierarchy. All subclasses override the same method(s). A subclass object reference is assigned to a superclass object reference. The superclass object reference is used to call the overridden method. 19
What Are Descendants? What types of objects can a reference variable refer to? A variable can hold a reference to an object whose class is a descendant of the class of the variable. A descendant of a class is a child of that class, or a child of a child of that class, and so on. Siblings are not descendants of each other You don t inherit anything from your brother or sister! 20
An Example Of Polymorphism In the example below we create a variable card of type Card We can now use this variable for any subclass of that superclass public class CardTesterV4 { public static void main ( String[] args ) { Card card = new Holiday( "Amy" ); card.greeting(); //Invoke a Holiday greeting() card = new Valentine( "Bob", 3 ); card.greeting(); //Invoke a Valentine greeting() card = new Birthday( "Cindy", 17 ); card.greeting(); //Invoke a Birthday greeting() } } 21
Snap Check 1 Here are some variable declarations: Card c; Birthday b; Valentine v; Holiday h; Which of the following are correct given our prior class definitions? c = new Valentine("Debby", 8); b = new Valentine("Elroy", 3); v = new Valentine("Fiona", 3); h = new Birthday ("Greg", 35); 22
Snap Check 1 Answers Card c; Birthday b; Valentine v; Holiday h; c = new Valentine("Debby", 8); //OK b = new Valentine("Elroy", 3); //WRONG v = new Valentine("Fiona", 3); //OK h = new Birthday ("Greg", 35); //WRONG 23
Snap Check 2 Given the definitions below and the Hierarchy to the left: Rodent rod; Rat rat; Mouse mou; Fill in the chart code section OK or Not? code section OK or Not? rod = new Rat(); mou = new Rat(); rat = new Rodent(); rat = new FieldMouse(); rod = new FieldMouse(); mou = new Rodent(); rat = new LabRat(); rat = new Mouse(); 24
Snap Check 2 Answers Giventhe definitions below and the Hierarchy to the left: Rodent rod; Rat rat; Mouse mou; Fill in the chart code section OK or Not? code section OK or Not? rod = new Rat(); mou = new Rat(); rat = new Rodent(); rat = new FieldMouse(); OK Wrong Wrong Wrong rod = new FieldMouse(); mou = new Rodent(); rat = new LabRat(); OK Wrong OK rat = new Mouse(); Wrong 25
Extending Classes and Polymorphism class YouthBirthday extends Birthday { public YouthBirthday ( String r, int years ) { super ( r, years ) } // additional method---does not override parent's method Different Signature public void greeting( String sender ) { super.greeting(); System.out.printf("How you have grown!!\n\n"); System.out.printf("Love, %s\n, sender); } } See CardTestV5.java, YouthBirthday.java, AdultBirthday.java 26
Referencing Subclass Objects with Subclass vs Superclass Reference A Deeper Explanation (1) There are two approaches to refer a subclass object. Both have some advantages/disadvantages over the other. The declaration affect is seen on methods that are visible at compile-time. First approach (Referencing using Superclass reference): A reference variable of a superclass can be used to a refer any subclass object derived from that superclass. If the methods are present in SuperClass, but overridden by SubClass, it will be the overridden method that will be executed. Second approach (Referencing using subclass reference) : A subclass reference can be used to refer its object. See Programs Bicycle.java, MountainBike.java, TestBikes.java 27
Referencing Subclass Objects with Subclass vs Superclass Reference A Deeper Explanation (2) The object of MountainBike class is created which is referred by using subclass reference mb1. MountainBike mb1 = new MountainBike(3, 100, 25); Using this reference we will have access both parts(methods and variables) of the object defined by the superclass or subclass. See below image for clear understanding. 28
Referencing Subclass Objects with Subclass vs Superclass Reference A Deeper Explanation (3) Now we again create object of MountainBike class but this time it is referred by using superclass Bicycle reference mb2. Using this reference we will have access only to those parts(methods and variables) of the object defined by the superclass. Bicycle mb2 = new MountainBike(4, 200, 20); 29
Referencing Subclass Objects with Subclass vs Superclass Reference A Deeper Explanation (4) If there are methods present in super class, but overridden by subclass, and if object of subclass is created, then whatever reference we use(either subclass or superclass), it will always be the overridden method in subclass that will be executed. In our example, we have seen that by using reference mb2 of type Bicycle, we are unable to call subclass specific methods or access subclass fields. In general, a superclass reference cannot reference subclass specific methods This problem can be solved using type casting in java. For example, we can declare another reference say mb3 of type MountainBike and assign it to mb2 using typecasting. // declaring MountainBike reference MountainBike mb3; // assigning mb3 to mb2 using typecasting. mb3 = (MountainBike)mb2; 30
Referencing Subclass Objects with Subclass vs Superclass Reference A Deeper Explanation (5) Summary Of Polymorphic Reference Usage subclass v. superclass Advantage We can use superclass reference to hold any subclass object derived from it. Disadvantage By using superclass reference, we will have access only to those parts(methods and variables) of the object defined by the superclass. For example, we can not access seatheight variable or call setheight(int newvalue) method using Bicycle reference in above first example. This is because they are defined in subclass not in the superclass. 31
The instanceof Operator (1) We ve already been using this operator in our equals() methods. Look at the example below: Object obj; YouthBirthday ybd = new YouthBirthday( "Ian", 4 ); String str = "Yertle"; obj = ybd; if ( obj instanceof YouthBirthday ) ((YouthBirthday)obj).greeting(); else if ( obj instanceof String ) System.out.printf( %s\n, (String)obj ); 32
The instanceof Operator (2) The format of instance of is: variable instanceof Class A typecast is used to tell the compiler what is really in a variable that itself is not specific enough. You have to tell the truth. In a complicated program, a reference variable might end up with any of several different objects, depending on the input data or other unpredictable conditions. The instanceof operator evaluates to true or false depending on whether the variable refers to an object of its operand. Also, instanceof will return true if variable is a descendant of Class. It can be a child, a grandchild, a greatgrandchild, or... of the class. 33
Programming Exercise 1 An abstract class Extending the abstract class Shape Create an abstract superclass Shape. Shape has two abstract methods, perimeter and area, and a final constant field named PI. Create two non-abstract subclasses, one encapsulating a Circle, the other a Rectangle. Rectangle has two additional attributes, length and width of type double. Circle has one additional attribute, its radius of type double. Write a TestShape class with a main method that tests out the above. Read in the length and width of a rectangle and print out the perimeter and area. Read in the radius of a rectangle and print out the perimeter (circumference) and area. 34