Chapter 10: Object Oriented Programming: Polymorphism (2023)

Table of Contents
Goals The plan 10.1 Introduction 10.2 Examples of polymorphisms Software Engineering Note 10.1 Software Engineering Observation 10.2 10.3 Demonstration of polymorphic behavior 10.4 Abstract Classes and Methods Software development observation 10.3 Common Programming Mistakes 10.1 Common Programming Error 10.2 10.5 Case Study: Payroll System with Polymorphism Software Engineering Observation 10.4 10.5.1 Creating an abstract superclass Employees 10.5.2 Creating a Concrete Employee Subclass 10.5.3 Create concrete HourlyEmployee subclasses 10.5.4 Create concrete subclasses of CommissionEmployee 10.5.5 Creating a Concrete Indirect Subclass BasePlusCommissionEmployee 10.5.6 Demonstration of polymorphic processing, operator instance and downcast Common Programming Error 10.3 Software Engineering Observation 10.5 Common Programming Error 10.4 10.5.7 Summary of allowed assignments between superclass and subclass variables 10.6 Final Methods and Classes Performance tip 10.1 Common Programming Error 10.5 10.7 Case Study: Creating and Using Interfaces Good Programming Practices 10.1 Common Programming Error 10.6 10.7.1 Development of a payment hierarchy Good Programming Practices 10.2 10.7.2 Declaration of the paid interface 10.7.3 Create Class Invoice 10.7.4 Modifying the employee class to implement the paid interface 10.7.5 Changing the salary class for use in the supplier hierarchy Software Engineering Note 10.7 Software Engineering Observation 10.8 Software Development Note 10.9 10.7.6 Using the payment interface for polymorphic processing of invoices and employees Software Engineering Note 10.10 10.7.7 Declaration of constants in interfaces Note of Software Development 10.11 10.7.8 General Java API Interfaces 10.8 (Optional) Software development case study: Integrating legacy into the ATM system Observation of software development 10.12 Software Development Note 10.13 10.9 Summary Videos
Chapter 10: Object Oriented Programming: Polymorphism (1)By Paul J. Deitel and Harvey M. Deitel
Posted by Prentice Hall
ISBN-10: 0-13-700129-0
ISBN-13: 978-0-13-700129-3

This chapter is an excerpt from the book Java for Programmers, written by Paul and Harvey Deitel, part of the Deitel Developer Series, ISBN 0137001290, published February 2009 by Prentice Hall Professional, copyright 2009 Pearson Education, Inc. Contact us for more information, visit :http://www.informit.com/store/product.aspx?isbn=0137001290Safari Books Online subscribers can access the book here:http://my.safaribooksonline.com/9780137018529

Goals

In this chapter you will learn:

  • The concept of polymorphism.
  • Use overridden methods to perform polymorphism.
  • Distinguish between abstract and concrete classes.
  • Declare abstract methods to create abstract classes.
  • How polymorphism makes systems extensible and maintainable.
  • To determine the type of an object at runtime.
  • Declare and implement interfaces.

One ring to rule them all, one ring to find them all, one ring to bring them all together and unite them in darkness.

John Ronald Reuel Tolkien

General propositions do not decide concrete cases.

Oliver Wendell Holmes

A philosopher of imposing stature does not think in a vacuum. Even his most abstract ideas are, to some extent, conditioned by what he is or is not known for at the time he lives.

Alfred North Whitehead

Why are you down, oh my soul?

Salmo 42:5

The plan

  • 10.1 Introduction
  • 10.2 Examples of polymorphisms
  • 10.3 Demonstration of polymorphic behavior
  • 10.4 Abstract Classes and Methods
  • 10.5 Case Study: Payroll System with Polymorphism
    • 10.5.1 Creating an abstract superclass Employees
    • 10.5.2 Creating a Concrete Employee Subclass
    • 10.5.3 Create concrete HourlyEmployee subclasses
    • 10.5.4 Create concrete subclasses of CommissionEmployee
    • 10.5.5 Creating a Concrete Indirect Subclass BasePlusCommissionEmployee
    • 10.5.6 Demonstration of polymorphic processing, operator instance and downcast
    • 10.5.7 Summary of allowed assignments between superclass and subclass variables
  • 10.6 Final Methods and Classes
  • 10.7 Case Study: Creating and Using Interfaces
    • 10.7.1 Development of a payment hierarchy
    • 10.7.2 Declaration of the paid interface
    • 10.7.3 Create Class Invoice
    • 10.7.4 Modifying the employee class to implement the paid interface
    • 10.7.5 Changing the salary class for use in the supplier hierarchy
    • 10.7.6 Using the payment interface for polymorphic processing of invoices and employees
    • 10.7.7 Declaration of constants in interfaces
    • 10.7.8 General Java API Interfaces
  • 10.8 (Optional) Software development case study: Integrating legacy into the ATM system
  • 10.9 Summary

10.1 Introduction

Now we continue our study of object-oriented programming by explaining and demonstratingPolymorphismwith inheritance hierarchies. Polymorphism allows us to "program in general" rather than "program in particular". In particular, polymorphism allows us to write programs that process objects that share the same superclass in a class hierarchy as if they were all objects of the superclass; this can simplify programming.

Consider the following polymorphism example. Suppose we create a program that simulates the movement of different animal species for a biological study. The fish, frog and bird classes represent the three animal species studied. Imagine that each of these classes extends the superclass Animal, which includes a Move method and maintains an animal's current location asxyCoordinates Each subclass implements the Move method. Our program maintains multiple references to objects from various subclasses of animals. To simulate the animals' movements, the program sends each object the same message, that is, movement, once a second. However, each specific animal species responds to a motion message in a unique way: a fish can swim a meter, a frog can jump a meter and a half, and a bird can fly a meter. The program outputs the same message (i.e. movement) to each animal object generically, but each object knows how to change its ownxyAppropriate coordinates for your specific type of movement. The key concept of polymorphism is trusting that each object knows how to "do the right thing" (that is, do what is appropriate for that type of object) in response to the same method call. The same message (motion in this case) sent to a multitude of objects will have "many shapes" of results, hence the term polymorphism.

Polymorphism allows us to design and implement easily extensible systems: new classes can be added to common parts of the program with little or no modification, as long as the new classes are part of the inheritance hierarchy that the program generically handles. The only parts of a program that need to be modified to accommodate new classes are those that require direct knowledge of the new classes the programmer is adding to the hierarchy. For example, if we extend the Animal class to create the Turtle class (which can respond to a motion message by crawling an inch), we only need to write the Turtle class and the part of the simulation that uses an instantiated Turtle object. The parts of the simulation that process each animal generically can remain the same.

This chapter consists of several parts. First, we discuss general examples of polymorphism. Next, we provide an example that demonstrates polymorphic behavior. We will use superclass references to polymorphically manipulate superclass and subclass objects.

Next, we present a case study that revisits the employee hierarchy from Section 9.4.5. We have developed a simple payroll application that polymorphically calculates weekly wages for several different types of employees using each employee's earnings method. While earnings are calculated specifically for each type of employee, polymorphism allows us to process employees "generally". In the case study, we've added two new classes to the hierarchy: white-collar workers (for people who pay a fixed weekly wage) and hourly workers (for people who pay by the hour and what's known as hour-and-a-half for overtime). 🇧🇷 We declare a common set of functions for all classes in the updated hierarchy in an abstract class, Employee, from which the SalariedEmployee, HourlyEmployee, and CommissionedEmployee classes inherit directly and the BasePlusCommissionedEmployee4 class indirectly. As you'll see shortly, due to Java's polymorphic features, the correct revenue calculation is performed when we call the Eye Employee Revenue method from a parent employee reference.

Occasionally, we need to program "for the details" in polymorphic processing. Our employee case study shows that a program can determine the type of an object at runtime and act accordingly. In the case study, we use these features to determine whether a given employee is opposed toIt is aBasePlusCommissionEmployee. In this case, we increase that employee's base salary by 10%.

The chapter then introduces the interfaces. An interface describes methods that can be invoked on an object, but does not provide concrete method implementations. that you can declare classesimplementprovide (that is, concrete implementations for the methods of) one or more interfaces. Every interface method must be declared in every class that implements the interface. Once a class implements an interface, all objects in that class have an interface.It is areference to the interface type, and all objects of the class are guaranteed to provide the functionality described by the interface. This also applies to all subclasses of this class.

Interfaces are particularly useful for assigning common functionality to potentially unrelated classes. This allows objects of unrelated classes to be processed polymorphically; Objects of classes that implement the same interface can respond to the same method calls. To demonstrate creating and using interfaces, we modified our payroll application to create a general accounts payable application that can calculate payments due from company employees and invoice amounts to be invoiced for purchased goods. As you'll see, interfaces allow for polymorphic capabilities similar to those possible with inheritance.

10.2 Examples of polymorphisms

Let's consider some other examples of polymorphism. If the Rectangle class derives from the Quadrilateral class, a Rectangle object is a more specific version of a Quadrilateral object. Any operation (such as perimeter or area calculation) that can be performed on a Quad object can also be performed on a Rectangle object. These operations can also be performed on other quadrilaterals, such as squares, parallelograms, and trapezoids. Polymorphism occurs when a program calls a method through a superclass variable; At runtime, the correct subclass version of the method is invoked based on the reference type stored in the superclass variable. You'll see a simple code example that demonstrates this process in Section 10.3.

As another example, suppose we design a video game that manipulates objects of classes Mars, Venus, Pluton, Spaceship, and LaserBeam. Imagine that each class inherits from the common superclass called SpaceObject, which contains the Draw method. Every subclass implements this method. A display manager maintains a collection (such as a SpaceObject array) of references to objects of various classes. To update the screen, the screen manager periodically sends each object the same message, Draw. However, each object reacts in a unique way. For example, an object on Mars might be drawn in red with green eyes and the appropriate number of antennae. A spaceship object might draw itself as a shiny silver flying saucer. A LaserBeam object can draw on the screen as a bright red beam. Again, the same message (Draw in this case) sent to a variety of objects will have "many shapes" of results.

A display administrator can use polymorphism to make it easy to add new classes to a system with minimal changes to system code. Suppose we want to add mercurian objects to our video game. To do this, we need to create a Mercurian class that extends SpaceObject and provides our own implementation of the Draw method. When objects of the Mercurian class appear in the SpaceObject collection, the display manager code calls the Draw method just as it would for any other object in the collection, regardless of its type. Therefore, the new Mercurian objects simply "plug in" without having to change the display manager code. Therefore, without modifying the system (other than creating new classes and modifying the code that creates new objects), programmers can use polymorphism to conveniently add additional types that were not expected when the system was created.

With polymorphism, the same method name and signature can be used to perform different actions depending on the type of object the method is called on. This gives the programmer enormous expressive power.

Software Engineering Note 10.1

Polymorphism allows programmers to handle the generalities and let the runtime handle the details. Programmers can instruct objects to behave appropriately for those objects without knowing the objects' types (as long as the objects belong to the same inheritance hierarchy).

Software Engineering Observation 10.2

Polymorphism promotes extensibility: software that invokes polymorphic behavior is independent of the object types to which messages are sent. New types of objects that can react to existing method calls can be integrated into a system without having to modify the underlying system. Only the client code that instantiates new objects needs to be modified to accommodate the new types.

10.3 Demonstration of polymorphic behavior

Section 9.4 created a hierarchy of commissioned employee classes in which the BasePlusCommissionEmployee class inherited from the CommissionEmployee class. The examples in this section manipulated the CommissionEmployee and BasePlusCommissionEmployee objects by using references to them to invoke their methods: we referred superclass references to superclass objects and subclass references to subclass objects. These assignments are natural and simple: superclass references refer to superclass objects, and subclass references refer to subclass objects. As you'll see shortly, however, other assignments are also possible.

In the following example, we use a superclass reference to refer to a subclass object. Next, we show how invoking a method on a subclass object through a superclass reference invokes the subclass's functionality: the type of the subclass.actual reference object, it's not the kind ofa warning, determines which method is called. This example demonstrates the key concept that an object of a subclass can be treated like an object of its superclass. This allows for several interesting manipulations. A program can create an array of superclass references that refer to objects of many subclass types. This is allowed because every subclass object is an object of its superclass. For example, we can assign the reference of a BasePlusCommissionEmployee object to a parent variable CommissionEmployee, since a BasePlusCommissionEmployeeIt is aFee Clerk: We may treat a BasePlus Fee Clerk as a Fee Clerk.

As you will learn later in this chapter, we cannot treat a superclass object as a subclass object because a superclass object is not an object of any of its subclasses. For example, we cannot assign a CommissionEmployee object reference to a BasePlusCommissionEmployee subclass variable because a CommissionEmployee is not a BasePlusCommissionEmployee; a CommissionEmployee does not have a baseSalary instance variable and does not have setBaseSalary and getBaseSalary methods. TheIt is aThe relationship only applies from a subclass to its direct (and indirect) superclasses and not vice versa.

The Java compiler allows a superclass reference to be assigned to a subclass variable if we explicitly convert the superclass reference to the subclass type, a technique we discuss in detail in Section 10.5. Why would we want to undertake such a task? A superclass reference can be used to invoke only those methods declared in the superclass; Attempting to invoke subclass-only methods through a reference to a superclass results in compile-time errors. When a program needs to perform a subclass-specific operation on a subclass object referenced by a superclass variable, the program must first convert the superclass reference to a subclass reference by a technique known asto tear down🇧🇷 This allows the program to call methods of subclasses that are not contained in the superclass. We show a concrete example of downcasting in Section 10.5.

The example in Figure 10.1 shows three ways to use superclass and subclass variables to store references to superclass and subclass objects. The first two are simple: as in Section 9.4, we assign a superclass reference to a superclass variable, and we assign a subclass reference to a subclass variable. Next, we prove the relationship between subclasses and superclasses (that is, theIt is arelationship) by assigning a subclass reference to a superclass variable. 🇧🇷To use:This program uses the CommissionEmployee3 and BasePlusCommissionEmployee4 classes from Figure 9.12 and Figure 9.13, respectively.]

In Figure 10.1, lines 10-11 create a CommissionEmployee3 object and assign its reference to a CommissionEmployee3 variable. Lines 14-16 create a BasePlusCommissionEmployee4 object and assign its reference to a BasePlusCommissionEmployee4 variable. These tasks are natural; For example, the main purpose of a CommissionEmployee3 variable is to hold a reference to a CommissionEmployee3 object. Lines 19-21 use the CommissionEmployee reference to call toString explicitly. Because CommissionEmployee references a CommissionEmployee3 object, the version of toString in the CommissionEmployee3 superclass is called. Similarly, lines 24 through 27 use basePlusCommissionEmployee to explicitly call toString on the BasePlusCommissionEmployee4 object. This calls the toString version of the BasePlusCommissionEmployee4 subclass.

1//Figure 10.1: PolymorphismTest.java 2//Assign superclass and subclass references to superclass and 3//subclass variables. 4 5public classPolymorphism Test6{7 AdvertisingstaticFileDirector(lineArguments[] )8{9 //Assign superclass reference to superclass variable10Employee commission3 Employee commission =neuProvisionMitarbeiter3(11 "Support financially","Jones","222-22-2222",10000, .06);1213 //Assign subclass reference to subclass variable14BasePlusProvisionEmployee4 basePlusProvisionEmployee =fifteen neuBasePlusComisiónEmpleado4(sixteen "Be for","Luis","333-33-3333",5000, .04,300);1718 //Calling toString on superclass object with superclass variable19System.Fora.printf("%s %s:\n\n%s\n\n",20 "Call the toString of CommissionEmployee3 with the superclass reference ",21 "to the object of the upper class", Employee Commission.toString() );2223 //Call toString on a subclass object using a subclass variable 24System.Fora.printf("%s %s:\n\n%s\n\n",25 "Call toString from BasePlusCommissionEmployee4 with subclass",26 "Reference to subclass object",27basePlusCommissionEmployee.toString() );2829 //Call toString on a subclass object using a superclass variable30ProvisionMitarbeiter3 ProvisionMitarbeiter2 =31basePlus employee commission;32System.Fora.printf("%s %s:\n\n%s\n",33 "Call a BasePlusCommissionEmployee4's toString with superclass",34 "Reference to subclass object", EmployeeCommission2.toString() );35}//last main36}//final class polymorphism test

PRODUCTION

Call EmployeeCommission3's aString with superclass reference to superclass object: Commission Employee: Sue Jones Social Security Number: 222-22-2222 Gross Sales: 10,000.00 Commission Rate: 0.06 Call BasePlus CommissionEmployee4's toString with subclass-to-subclass referenceObject:Commission Officer Base Salary: Bob LewisSocial Security Number: 333-33-3333Gross Sales:5000.00Commission percentage:0.04BaseWage:300.00Ligue para BasePlusProvisionEmployee4's toString with superclass reference to subclass object: Commission Employees with Base Salary: Bob Lewis Social Security Number: 333-33-3333 Gross Sales: 5,000.00 Commission Rate: 0.04 Base Salary: 300.00

Figure 10.1Assigning superclass and subclass references to superclass and subclass variables.

Lines 30-31 then assign the reference to the basePlusCommissionEmployee subclass object to a parent variable CommissionEmployee3, which is used in lines 32-34 to call the toString method. If a superclass variable contains a reference to a subclass object and that reference is used to invoke a method, the subclass version of the method is invoked. So, on line 34, CommissionEmployee2.toString() actually calls the toString method of the BasePlusCommissionEmployee4 class. The Java compiler allows this "crossover" because an object is a subclassIt is aobject of its superclass (but not vice versa). When the compiler encounters a method call made through a variable, the compiler determines whether the method is callable by checking the class type of the variable. If this class contains (or inherits from) the appropriate method declaration, the call will compile. At runtime, the type of object the variable refers to determines the actual method to be used.

10.4 Abstract Classes and Methods

When we think of a class type, we assume that programs create objects of that type. In some cases, however, it makes sense to declare classes for which the programmer never intends to instantiate objects. Such classes are calledabstract classes🇧🇷 Since they are only used as superclasses in inheritance hierarchies, we refer to them asabstract superclasses🇧🇷 These classes cannot be used to instantiate objects because, as we'll see shortly, abstract classes are incomplete. Subclasses must declare the "missing parts". We demonstrate abstract classes in Section 10.5.

(Video) Chapter 10 Object Oriented Programming Polymorphism and Interfaces Part 1

The purpose of an abstract class is to provide a convenient superclass from which other classes can inherit and thus share a common design. For example, in the hierarchy of shapes in Figure 9.3, subclasses inherit the notion of what it means to be a shape: shared attributes like edge position, color, and thickness, and behaviors like drawing, moving, resizing, and changing the shape. Classes are called which can be used to instantiate objectsconcrete classrooms🇧🇷 These classes provide implementations of each method they declare (some of the implementations can be inherited). For example, we could derive the concrete classes Circle, Square, and Triangle from the abstract superclass TwoDimensionalShape. Likewise, we could derive the concrete classes sphere, cube, and tetrahedron from the three-dimensional shape of the abstract superclass. Abstract superclasses are too general to create real objects: they just specify what the subclasses have in common. We need to be more specific before we can create objects. For example, if you send the drawing message to the abstract TwoDimensionalShape class, you know that two-dimensional shapes must be drawable, but you don't know which specific shape to draw, so you can't implement an actual drawing method. Concrete classes provide the details that make it useful for instantiating objects.

Not all inheritance hierarchies contain abstract classes. However, programmers often write client code that uses only abstract superclass types to reduce client code dependencies on a set of subclass-specific types. For example, a programmer could write a method with a parameter of an abstract superclass type. When called, such a method can take an object of any concrete class that directly or indirectly extends the superclass specified as the parameter's type.

Abstract classes sometimes form multiple levels of the hierarchy. For example, the hierarchy of shapes in Figure 9.3 starts with the abstract class Shape. At the next level in the hierarchy are two more abstract classes, TwoDimensionalShape and ThreeDimensionalShape. The next level of the hierarchy declares concrete classes for two-dimensional shapes (circle, square, and triangle) and for three-dimensional shapes (sphere, cube, and tetrahedron).

You create an abstract class by declaring it with a keywordabstract🇧🇷 An abstract class usually contains one or moreabstract methods🇧🇷 An abstract method is one with the keyword abstract in its declaration, as in

AdvertisingabstractFileto draw();// abstract method

Abstract methods do not provide implementations. A class that contains abstract methods must be declared as an abstract class, even if that class contains some concrete (non-abstract) methods. Each concrete subclass of an abstract superclass must also provide concrete implementations of each of the superclass's abstract methods. Constructors and static methods cannot be declared abstract. Constructors are not inherited, so an abstract constructor could never be implemented. Although static methods are inherited, they are not associated with specific objects of the classes that declare the static methods. Since abstract methods must be overridden so that they can operate on objects based on their types, declaring an abstract static method would make no sense.

Software development observation 10.3

An abstract class declares attributes and behaviors common to the various classes in a class hierarchy. An abstract class usually contains one or more abstract methods that subclasses must override if the subclasses are concrete. Instance variables and concrete methods of an abstract class are subject to the normal rules of inheritance.

Common Programming Mistakes 10.1

Attempting to instantiate an object of an abstract class is a compiler error.

Common Programming Error 10.2

Not implementing the abstract methods of a superclass in a subclass is a compiler error unless the subclass is also declared abstract.

Although we cannot instantiate objects of abstract superclasses, you will soon see that we can use abstract superclasses to declare variables that can hold references to objects of any concrete class derived from these abstract superclasses. Programs often use these variables to polymorphically manipulate subclass objects. We can also use abstract superclass names to invoke static methods declared in those abstract superclasses.

Consider another application of polymorphism. A drawing program must display many shapes, including new types of shapes that the programmer adds to the system after writing the drawing program. The drawing program may need to display shapes such as circles, triangles, rectangles, or others derived from the abstract Shape superclass. The drawing program uses shape variables to manage the objects that are displayed. To draw any object in this inheritance hierarchy, the drawing program uses a superclass Shape variable that contains a reference to the subclass object to invoke the object's drawing method. This method is declared in superclass Shape as abstract, that is, any concrete subclasshave toImplement the Draw method in a specific shape for this shape. Every object in the shape inheritance hierarchy knows how to draw itself. The drawing program doesn't have to worry about what type each object is or whether the drawing program has already found objects of that type.

Polymorphism is particularly effective for implementing so-called layered software systems. In operating systems, for example, each type of physical device can function very differently from the others. Despite this, the commands for reading or writing data to and from devices can have some consistency. For each device, the operating system uses software called a device driver to handle all communication between the system and the device. The write message sent to a device driver object must be interpreted specifically in the context of that driver and how it handles devices of a specific type. However, the recording call itself is no different than recording on any other device in the system: put a certain number of bytes of memory on this device. An object-oriented operating system could use an abstract superclass to provide a convenient "interface" for all device drivers. Then, through inheritance, subclasses are formed from this abstract superclass that behave similarly. Device driver methods are declared as abstract methods in the abstract superclass. Implementations of these abstract methods are provided in subclasses that correspond to specific types of device drivers. New devices are constantly being developed, often long after the operating system has been released. When you buy a new device, it comes with a device driver provided by the device manufacturer. The device is ready to use as soon as you connect it to your computer and install the driver. This is another elegant example of how polymorphism makes systems extensible.

In object-oriented programming, it is common to declare aiterator classthat can iterate over all objects in a collection, such as an Array (Chapter 7) or an ArrayList (Chapter 16, Collections). For example, a program can print an ArrayList of objects by creating an iterator object and using it to get the next element in the list each time the iterator is called. Iterators are commonly used in polymorphic programming to iterate through a collection that contains references to objects at different levels of a hierarchy. (Chapter 16 contains a full discussion of ArrayLists, iterators, and "generic" features.) For example, an ArrayList of objects of class TwoDimensionalShape can contain objects of subclasses Square, Circle, Triangle, and so on. Calling the Draw method on each TwoDimensionalShape object from a TwoDimensionalShape variable would polymorphically draw each object correctly to the screen.

10.5 Case Study: Payroll System with Polymorphism

This section revisits the CommissionEmployee-BasePlusCommissionEmployee hierarchy that we explored in Section 9.4. We now use an abstract method and polymorphism to perform salary calculations based on employee type. We created an improved employee hierarchy to address the following issue:

    A company pays its employees weekly. There are four types of workers: salaried workers are paid a fixed weekly wage regardless of the number of hours worked, hourly workers are paid by the hour and receive overtime pay for any hours worked beyond 40 hours, commission workers are paid a percentage of their sales representatives and commission agents receive a base salary plus a percentage of their sales. For the current compensation period, the company has decided to reward employees on a commission basis with a 10% premium on base salary. The company wants to implement a Java application that will do its payroll polymorphically.

We use the Employee abstract class to represent the general concept of an employee. Classes that extend Employee are Salary, CommissionEmployee, and HourlyEmployee. The BasePlusCommissionEmployee class, which extends CommissionEmployee, represents the last type of employee. The UML class diagram inFigure 10.2shows the inheritance hierarchy for our polymorphic payroll application. Note that the Employee abstract class is shown in italics, following UML convention.

Chapter 10: Object Oriented Programming: Polymorphism (2)

Figure 10.2 Employee hierarchy UML class diagram.

The abstract superclass Employee declares the "interface" to the hierarchy, that is, the set of methods that a program can call on all Employee objects. We use the term "interface" here in a generic sense to refer to the various ways in which programs can communicate with objects of any subclass of Employee. Be careful not to confuse the general notion of "interface" with the formal notion of Java interface, the subject of Section 10.7. Every employee has a first name, last name, and social security number, regardless of how their income is calculated; therefore, the private instance variables firstName, lastName, and socialSecurityNumber appear in the abstract superclass Employee.

Software Engineering Observation 10.4

A subclass can inherit "interface" or "implementation" from a superclass. hierarchies for meimplementation inheritanceThey tend to have their functionality high up in the hierarchy: each new subclass inherits one or more methods implemented in a superclass, and the subclass uses the superclass's implementations. Hierarchies designed tointerface inheritanceThey tend to have their functionality lower in the hierarchy: a superclass specifies one or more abstract methods that must be declared for each concrete class in the hierarchy, and individual subclasses override these methods to provide subclass-specific implementations.

The following sections implement the employee class hierarchy. Each of the first four sections implements one of the concrete classes. The last section implements a test program that constructs objects of all these classes and processes them polymorphically.

10.5.1 Creating an abstract superclass Employees

The Employee class (Figure 10.4) provides gain, toString, get, and set methods that manipulate the Employee instance variables. A winning method certainly applies universally to all employees. However, each earnings calculation depends on the class of worker. Therefore, we declare the recipe in the Employee superclass as abstract, as a default implementation for this method makes no sense: there is not enough information to determine how much revenue it should return. Each subclass replaces the gains with an appropriate implementation. To calculate an employee's earnings, the program assigns a reference to the superclass employee variable to the employee object and then invokes the earnings method on that variable. We maintain an array of Employee variables, each containing a reference to an Employee object (of course there can be no Employee objects since Employee is an abstract class; however, due to inheritance any Employee object can be any subclass for Employee to be considered as employee objects). The program iterates through the array and calls the Earnings method for each Employee object. Java handles these method calls polymorphically. Including "Earnings" as an abstract method in "Employee" forces any direct subclass of "Employee" to override "Earnings" to become a concrete class. This allows the designer of the class hierarchy to require each concrete subclass to provide an appropriate pay calculation.

The toString method of the Employee class returns a string containing the employee's first name, last name and CPF. As we'll see, each subclass of Employee overrides the toString method to create a string representation of an object of that class that contains the employee's type (for example, "Employee:") followed by the rest of the employee's information.

The diagram inFigure 10.3shows each of the five classes in the hierarchy on the left and the Earnings and toString methods on the top. For each class, the graph shows the desired results of each method. 🇧🇷To use:We do not list superclass employeesto receivejFoundbecause they don't override in any of the subclasses; each of these subclasses inherits and uses each of these methods "as is".]

Chapter 10: Object Oriented Programming: Polymorphism (3)

Figure 10.3 Polymorphic Interface for Employee Hierarchy Classes.

Consider the declaration of the Employee class (Figure 10.4). The class contains a constructor that takes first name, last name, and social security number as arguments (lines 11-16); get methods that return first name, last name and CPF (lines 25-28, 37-40 and 49-52, respectively); establish methods that determine first name, last name and CPF (lines 19-22, 31-34 and 43-46, respectively); method toString (lines 55-59), which returns the string representation of Employee; and gains per abstract method (line 62) implemented by subclasses. Note that the Employee constructor does not validate the social security number in this example. Such validation should normally be provided.

Why did we choose to report the recipe as an abstract method? It just doesn't make sense to provide an implementation of this method in the Employee class. We cannot calculate an employee's overall income; We must first know the specific type of employee to determine the correct calculation of income. By declaring this abstract method, we indicate that each concrete subclass must provide an appropriate income implementation, and that a program can use employee variables from the superclass to polymorphically invoke the income method for any type of employee.

1 //Figure 10.4: Employee.java2 //Employee abstract upper class.34 Advertisingabstractclassemployee5{6 Private lineFirst name;7 Private lineLast name;8 Private linesocial Security number;910 //Constructor with three arguments11 AdvertisingEmployee(lineFirst,linelast,linesn)12{13firstname = first;14lastname = lastname;fifteenCPF = ssn;sixteen}//Exit employee constructor with three arguments1718 //Enter the name19 public voidEnter the name(lineFirst )20{21firstname = first;22}//last method setFirstName2324 //return the name25 Advertising linegetFirstName()26{27 give backFirst name;28}//last method getFirstName2930 //set surnames31 public voidestablecerApellido(linelast )32{33lastname = lastname;34}//last method setLastName3536 //return last name37 Advertising linegetLastName()38{39 give backLast name;40}//last method getLastName4142 //Set social security number43 public voidsetNúmeroSeguridadSocial(linesn)44{45CPF = ssn;//must validate46}//last method setSocialSecurityNumber4748 //Return social security number49 Advertising linegetSocialSecurityNumber()50{51 give backsocial Security number;52}//last getSocialSecurityNumber method5354 //return Stringdarstellung des Employee-Objekts55 Advertising lineChain()56{57 give back line.Format("%s %s\nSocial Security Number: %s",58getFirstName(), getLastName(), getSocialSecurityNumber());59}//final toString method6061 //abstract method replaced by subclasses62 Advertisingabstracterm goodprofit();//no implementation here63}//terminate the Employee abstract class

Figure 10.4: Abstract superclass “Employee”.

10.5.2 Creating a Concrete Employee Subclass

Class SalaryEmployee (Figure 10.5) extends class Employee (line 4) and replaces Income (lines 29-32), making SalaryEmployee a concrete class. The class contains a constructor (lines 9-14) that takes a first name, last name, social security number, and weekly wage as arguments; a method defined for assigning a new non-negative value to the WeeklySalary instance variable (lines 17-20); a get method to return the weekly wage amount (lines 23-26); an income method (lines 29-32) for calculating an employee's income; and a toString method (lines 35-39) that returns a String containing the type of employee, ie "employee salary:" followed by employee-specific information retrieved from the toString method of the parent Employee class and the getWeeklySalary method of SalriedEmployee. The constructor of the SalariedEmployee class passes the first, last, and social security number to the Employee constructor (line 12) to initialize private instance variables not inherited from the superclass. The Earnings method overrides Employee's abstract Earnings method to provide a concrete implementation that returns the weekly salary for SalriedEmployee. If we do not implement a yield, the SalariedEmployee class must be declared as abstract; otherwise, a compiler error will occur (and of course we want SalariedEmployee to be a concrete class).

1 //Figure 10.5: SalaryEmployee.java2 //A class SalariedEmployee stands for Employee.34 public classpaid employeeexpandedemployee5{6 doubly privateweekly salary;78 //Constructor with four arguments9 AdvertisingPaid employee (lineFirst,linelast,linesn,10 erm goodWage)11{12 super(first, last, ssn);//Switch to Employee Builder13setWeeklySalary(salary);//Validate and save salary14}//Complete salaried employee constructor with four argumentsfifteensixteen //fixed salary17 public voidestablecerSalarioSemanal(erm goodWage)18{19Weekly salary = salary <0.0?0.0: Wage;20}//last method definedWeeklySalary2122 //salary back23 doubly publicgetWeeklySalary()24{25 give backweekly salary;26}//Method final getWeeklySalary2728 //calculate yield; replace abstract method gains //in the official29 doubly publicprofit()30{31 give backgetWeeklySalary();32}//Result of the final method3334 //returns the string representation of the SalaryEmployee object35 Advertising lineChain()36{37 give back line.Format("Employee: %s\n%s: $%,.2f",38 super.Chain(),"weekly wage", getWeeklySalary() );39} //final toString method40}//Employed graduation class

Figure 10.5 Classe Employee derived from Employee.

The toString method (lines 35-39) of the SalariedEmployee class overrides the Employee toString method. If the SalaryEmployee class did not override toString, SalaryEmployee would have inherited the Employee version of toString. In this case, SalaryEmployee's toString method would simply return the employee's full name and social security number, which does not properly represent a SalaryEmployee. To produce a complete string representation of an employee, the subclass's toString method returns "salaried employee:" followed by the superclass employee's specific information (that is, first name, last name, and social security number), obtained by calling the toString method of the superclass. superclass (Line 38): This is a good example of code reuse. The string representation of an employee also contains the employee's weekly salary, which is obtained by calling the class's getWeeklySalary method.

10.5.3 Create concrete HourlyEmployee subclasses

Class HourlyEmployee (Figure 10.6) also extends Employee (line 4). The class contains a constructor (lines 10 to 16) that takes as arguments the first name, last name, social security number, hourly rate and number of hours worked. Lines 19-22 and 31-35 declare set methods that assign new values ​​to the instance variables salary and time, respectively. Method setWage (lines 19-22) ensures that salary is not negative, and method setHours (lines 31-35) ensures that hours are between 0 and 168 (the total number of hours in a week). Class HourlyEmployee also contains get methods (lines 25-28 and 38-41) to return wage and hour values, respectively; an earnings method (lines 44-50) for calculating employee hourly earnings; and a toString method (lines 53-58) that returns the employee type, which is "Hourly Employee:" and employee-specific information. Note that, like the SalariedEmployee constructor, the HourlyEmployee constructor passes the first, last, and social security number to the constructor of the superclass Employee (line 13) to initialize the private instance variables. Furthermore, the toString method calls the superclass's toString method (line 56) to obtain the employee's specific information (ie, first name, last name, and social security number); This is another good example of code reuse.

1 //Figure 10.6: HourlyEmployee.java2 //A classe HourlyEmployee estende Employee.34 public classhourly employeeexpandedemployee5{6 doubly privateWage;//hourly wage7 doubly privatePattern;//hours worked per week89 //Constructor with five arguments10 Advertisingemployees per hour (lineFirst,linelast,linesn,11 erm goodhourly wage,erm goodworkday)12{13 super(first, last, ssn);14setLohn(salarioporhora);//Confirm hourly wagefifteensetHours(horasTrabajadas);//Validate working hourssixteen}//Exit the HourlyEmployee constructor with five arguments1718 //fixed salary19 public voidset salary (erm goodhourly rate)20{21salary = (hourly wage <0.0) ?0.0: wage per hour;22}//final setWage method2324 //salary paid25 doubly publicearnings()26{27 give backWage;28}//last method getWage2930 //Set working hours31 public voidsetHours(erm goodworkday)32{33Hours = ( ( Hours worked >=0.0) && (working hours <=168.0) ) ?34workday:0.0;35}//Method final setHours3637 //return of hours worked38 doubly publicgetHoras()39{40 give backPattern;41}//last method of getHour4243 //calculate yield; override abstract method //income on employee44 doubly publicprofit()45{46 e(getHours() <=40)//no overtime47 give backgetSalary() * getHours();48 Most49 give back 40* getGehalt() + (gethours() -40) * to receive salary () *1.5;50}//Result of the final method5152 //returns the string representation of the HourlyEmployee object53 Advertising lineChain()54{55 give back line.Format("Hourly employees: %s\n%s: $%,.2f; %s: %,.2f",56 super.Chain(),"hourly wage", to receive salary(),57 "workday", getHoras() );58}//final toString method59}//Hourly Clerk Graduation Class

Figure 10.6 Class HourlyEmployee derived from Employee.

(Video) Chapter 10 Object Oriented Programming Polymorphism and Interfaces Part 2

10.5.4 Create concrete subclasses of CommissionEmployee

The CommissionEmployee class (Figure 10.7) extends the Employee class (line 4). The class contains a constructor (lines 10-16) that takes a first name, last name, social security number, sales amount, and commission rate; Configure the methods (lines 19-22 and 31-34) to assign new values ​​to the CommissionRate and GrossSales instance variables, respectively; get methods (lines 25-28 and 37-40) that retrieve the values ​​of these instance variables; Income method (lines 43-46) for calculating a commission agent's income; and the toString method (lines 49-55), which returns the employee type, which is "commissioned employee:" and employee-specific information. The constructor also passes the first, last, and social security number to the Employee constructor (line 13) to initialize Employee's private instance variables. Method toString calls the superclass's toString method (line 52) to get the employee's specific information (ie, first name, last name, and social security number).

1 //Figure 10.7: CommissionEmployee.java2 //A classe CommissionEmployee estende Employee.34 public classcommission staffexpandedemployee5{6 doubly privategross sales;//gross weekly sales7 doubly privatecommission percentage;//commission percentage89 //Constructor with five arguments10 Advertisingcommission staff (lineFirst,linelast,linesn,11 erm goodOffer,erm goodSpeed)12{13 super(first, last, ssn);14setGrossSales(sales);fifteensetProvisionsrate (Taxa);sixteen}//Exit the CommissionEmployee constructor with five arguments1718 //Set commission rate19 public voidsetTasaComisión(erm goodSpeed)20{21fee = (fee >0.0&& Course <1.0🇧🇷 Speed:0.0;22}//método final setCommissionRate2324 //return commission rate25 doubly publicgetCommissionRate()26{27 give backcommission percentage;28}//last method getCommissionRate2930 //Define gross sales amount31 public voidsetWaitsSubtracted(erm goodoffer)32{33Gross Sales = (Sales <0.0) ?0.0: offer;34}//last setGrossSales method3536 //return the gross amount of sales37 doubly publicgetGrossSales()38{39 give backgross sales;40}//last method getGrossSales4142 //calculate yield; replace abstract method gains //in the employee43 doubly publicprofit()44{45 give backgetCommissionRate() * getGrossSales();46}//Result of the final method4748 //CommissionEmployee object return string representation49 Advertising lineChain()50{51 give back line.Format("%s: %s\n%s: $%,.2f; %s: %.2f",52 "commission staff",super.Chain(),53 "gross sales", getGrossSales(),54 "commission percentage", getCommissionRate() );55}//final toString method56}//Final Class CommitteeMitarbeiter

Figure 10.7 The CommissionEmployee class derived from Employee.

10.5.5 Creating a Concrete Indirect Subclass BasePlusCommissionEmployee

The BasePlusCommissionEmployee class (Figure 10.8) extends the CommissionEmployee class (line 4) and is therefore an indirect subclass of the Employee class. Class BasePlusCommissionEmployee has a constructor (lines 9-14) that accepts as arguments first name, last name, social security number, sales amount, commission rate, and base salary. It then passes the first name, last name, social security number, sales amount, and commission rate to the CommissionEmployee builder (line 12) to initialize the inherited items. BasePlusCommissionEmployee also contains a set method (lines 17-20) to assign a new value to the baseSalary instance variable and a get method (lines 23-26) to return the value of baseSalary. The income method (lines 29-32) calculates the income of a BasePlusProvisionEmployee. Notice that line 31 in the income method calls the income method of the parent class CommissionEmployee to calculate the commission-based portion of the employee's income. This is a good example of code reuse. BasePlusCommissionEmployee's toString method (lines 35-40) creates a string representation of a BasePlusCommissionEmployee that contains "Base Salary" followed by the string obtained by calling the superclass CommissionEmployee's toString method (another example of code reuse). , then base salary. The result is a string that starts with "Employee Base Salary Commission" followed by the rest of the BasePlusCommissionEmployee information. Recall that CommissionEmployee's toString obtains the employee's first, last, and social security number by calling the toString method of its superclass (that is, Employee), another example of code reuse. Note that BasePlusCommissionEmployee toString starts a chain of method calls spanning all three levels of the employee hierarchy.

1 //Figure 10.8: BasePlusCommissionEmployee.java2 //A classe BasePlusCommissionEmployee estende CommissionEmployee.34 public classBasePlusCommissionEmployeeexpandedcommission staff5{6 doubly privatebase salary;//base salary per week78 //Constructor with six arguments9 AdvertisingBasisPlusMitarbeiterProvision(lineFirst,linelast,10 linesn,erm goodOffer,erm goodSpeed,erm goodWage)11{12 super(name, surname, ssn, sales, rate);13setBaseSalary(salary);//Validate and save base salary14}//Complete the BasePlusCommissionEmployee constructor with six argumentsfifteensixteen //fixed base salary17 public voidestablecerSalarioBase(erm goodWage)18{19Base Salary = ( Salary <0.0) ?0.0: Wage;//not negative20}//last method setBaseSalary2122 //return base salary23 doubly publicgetBaseSalary()24{25 give backbase salary;26}//last method getBaseSalary2728 //calculate yield; The reversal method is gaining importance //commission staff29 doubly publicprofit()30{31 give backgetSalaryBase() +super.profit();32}//Result of the final method3334 //BasePlusCommissionEmployee return string representation //Object35 Advertising lineChain()36{37 give back line.Format("%s %s; %s: $%,.2f",38 "Core values",super.Chain(),39 "base salary", getBaseSalary() );40}//final toString method41}//classe final BasePlusProvisionEmployee

Figure 10.8 BasePlusCommissionEmployee derives from CommissionEmployee.

10.5.6 Demonstration of polymorphic processing, operator instance and downcast

To test our employee hierarchy, the application in Figure 10.9 creates an object from each of four concrete classes: SalaryEmployee, HourlyEmployee, CommissionedEmployee, and CommissionedEmployeeBasePlus. The program manipulates these objects first through variables of each object type and then polymorphically using an array of employee variables. When processing objects polymorphically, the program increases the base salary of each BasePlusProvisionEmployee by 10% (obviously, this requires that the object type be determined at runtime). Finally, the program polymorphically determines and generates the type of each object in the array of employees. Lines 9-18 create objects for each of the four concrete employee subclasses. Lines 22-30 create the string representation and gains for each of these objects. Note that printf implicitly calls each object's toString method if the object is printed as a string with the %s format specifier.

1 //Figure 10.9: PayrollSystemTest.java2 //Test program for employee hierarchies.34 public classPayroll system test5{6 AdvertisingstaticFileDirector(lineArguments[] )7{8 //Create subclass objects9employee employee =10 neuPaid employee ("John","Herrero","111-11-1111",800.00);11Employees per hour Employees per hour =12 neuemployees per hour ("karen","Preis","222-22-2222",sixteen.75,40);13CommissionEmployee CommissionEmployee =14 neucommission staff (fifteen "Support financially","Jones","333-33-3333",10000, .06);sixteenBasePlusCommissionEmployee basePlusCommissionEmployee =17 neuBasisPlusMitarbeiterProvision(18 "Be for","Luis","444-44-4444",5000, .04,300);1920System.Fora.println("Employees Processed Individually:\n");2122System.Fora.printf("%s\n%s: $%,.2f\n\n",23paid employee,"Bed", employee.earnings() );24System.Fora.printf("%s\n%s: $%,.2f\n\n",25hourly employee,"Bed", hourly employee.Revenue() );26System.Fora.printf("%s\n%s: $%,.2f\n\n",27commission staff,"Bed", Commission from employee.earn() );28System.Fora.printf("%s\n%s: $%,.2f\n\n",29baseplus commission employee,30 "Bed", basePlusCommissionEmployee.earnings() );3132 //Create a four-element array of employees33Employee Employee[] =neuEmployee[4];3435 //Initialize array with employees36Employee[0] = employee;37Employee[1] = hourly employee;38Employee[2] = commission staff;39Employee[3] = basePlusComissionEmployee;4041System.Fora.println("Polymorphic processed employee:\n");4243 //In general, process each element in array employees44 through the(Employee Current Employee: Employee)45{46System.Fora.println(current employee);//call the jail4748 //Determine if the item is a BasePlusCommissionEmployee49 e(current employeeRather thanBasePlusComissionEmployee )50{51 //discouraged employee pointing to52 //BasePlusCommissionEmployee Reference53Employer BasicPlusCommissionEmployee =54(BasePlusProvisionEmployee) current employee;5556 erm goodoldbasalsalary = employee.getbasicsalary();57employee.setBaseSalary(1.10* old base salary);58System.Fora.printf(59 "new base salary with a 10% raise is: $%,0,2f\n",60employee.getBaseSalary() );61}//would end when6263System.Fora.printf(64 "earned $%,.2f\n\n", CurrentEmployee.earnings() );Sixty-five}//finish with6667 //Get the type name of each object in the array of employees68 through the(e Tj =0🇧🇷 j < employee.length; j++)69System.Fora.printf("Employee %d is a %s\n", j,70empleados[ j ].getClass().getName() );71}//last main72}//Class salary system final test

PRODUCTION

Individually Processed Employees: Employee: John Smith Social Security Number: 111-11-1111 Weekly Salary: $800.00won: $800.00Hourly Employee: Karen Price Social Security Number: 222-22-2222 Hourly Rate: $16.75🇧🇷 workday:40.00earned: $670.00Commission Officer: Sue Jones Social Security Number: 333-33-3333 Gross Sales: $10,000.00🇧🇷 Commission percentage:0.06Won: $600.00Commission Agent Base Salary: Bob Lewis Social Security Number: 444-44-4444 Gross Sales: $5.000.00🇧🇷 Commission percentage:0.04;BaseSalary: $300.00won: $500.00Prosecuted Polymorph Employees: Employee: John Smith Social Security Number: 111-11-1111 Weekly Salary: $800.00Won $800.00Hourly Employee: Karen Price Social Security Number: 222-22-2222 Hourly Rate: $16.75🇧🇷 workday:40.00Won $670.00Commission Officer: Sue Jones Social Security Number: 333-33-3333 Gross Sales: $10,000.00🇧🇷 Commission percentage:0.06Won $600.00Commission Agent Base Salary: Bob Lewis Social Security Number: 444-44-4444 Gross Sales: $5.000.00🇧🇷 Commission percentage:0.04;BaseSalary: $300.00neu BaseSalary with 10% increasees$ 330.00earned $530.00employee0 esa hired employee1 esone employee per hour2 esfor Commission Employee Employee3 esa BasePlus commission agent

Figure 10.9 Employee class hierarchy test program.

Line 33 declares the employees and assigns them an array of four employee variables. Line 36 assigns the reference to a SalariedEmployee object to employee[ 0 ]. Line 37 assigns the reference to an HourlyEmployee object to employee[ 1 ]. Line 38 assigns the reference to a CommissionEmployee object to employee[ 2 ]. Line 39 assigns employee[ 3 ] a reference to a BasePlusCommissionEmployee object. Any bet is allowed because an officialIt is aemployees, one employee per hourIt is aofficial, commission officialIt is aEmployee and BasePlusProvisionEmployee is an Employee. So, even though Employee is an abstract class, we can assign the SalariedEmployee, HourlyEmployee, CommissionedEmployee, and CommissionBasePlusEmployee object references to the Employee superclass variables.

Lines 44-65 loop through the Employee array and call the toString and Earnings methods with the Employee Current Employee control variable. The result shows that the appropriate methods are actually called for each class. All calls to the toString method and receipts are resolved at runtime, depending on the type of object referenced by the current contributor. This process is known asdynamic joinÖlate call🇧🇷 For example, line 46 implicitly calls the toString method of the object referenced by the current employee. As a result of dynamic binding, Java decides which class's toString method to call at runtime rather than compile time. Note that only methods of the Employee class can be invoked through an Employee variable (and, of course, Employee includes methods of the Object class). (Section 9.7 covers the set of methods that all classes inherit from the Object class.) A superclass reference can be used to invoke only superclass methods (and the superclass can invoke overridden versions of them in the subclass).

We perform special processing on BasePlusCommissionEmployee objects: if we find these objects, we increase your base salary by 10%. When processing objects polymorphically, we generally don't need to worry about the "details", but to match the base salary, we need to determine the specific type of the Employee object at runtime. Line 49 uses theRather thanto determine if a specific employee's object type is BasePlusCommissionEmployee. The condition on line 49 is true if the object pointed to by currentEmployeeIt is aBasePlusCommissionEmployee. This also applies to any object of a BasePlusCommissionEmployee subclass, as it isIt is aRelationship that a subclass has with its superclass. Lines 53-54 cast currentEmployee from type Employee to type BasePlusCommissionEmployee: This conversion is allowed only if the object has an is-one relationship with BasePlusCommissionEmployee. The condition on line 49 ensures that this is the case. This conversion is necessary when calling the getBaseSalary and setBaseSalary methods of the BasePlusCommissionEmployee subclass on the current Employee object; As you'll see shortly, trying to call a subclass-only method directly on a superclass reference is a compiler error.

Common Programming Error 10.3

Assigning a superclass variable to a subclass variable (without an explicit cast) is a compiler error.

Software Engineering Observation 10.5

At runtime, if a subclass object's reference has been assigned to a variable of one of its direct or indirect superclasses, it is acceptable to convert the reference stored in that superclass variable back to a reference of the subclass type. Before performing this conversion, use the instanceof operator to ensure that the object really is an object of an appropriate subclass type.

Common Programming Error 10.4

Downcasting an object throws a ClassCastException if the object does not have an is-one relationship with the type specified in the cast operator at runtime. An object can only be converted to its own type or to the type of one of its superclasses.

If the instanceof expression on line 49 is true, the body of the if statement (lines 49-61) performs the special processing required by the BasePlusCommissionEmployee object. Using the employee variable BasePlusCommissionEmployee, lines 56 and 57 call the subclass-only methods getBaseSalary and setBaseSalary to retrieve and update the employee's base salary with the 10% increase.

Lines 63 and 64 call the Earnings method for CurrentEmployee, which polymorphically calls the Earnings method of the corresponding subclass object. As you can see, polymorphically retrieving the income for administrative, hourly, and commission employees in lines 63-64 gives the same result as retrieving the income for those employees individually in lines 22-27. However, the earnings earned by BasePlusProvisionEmployee in lines 63- 64 is greater than the earnings in rows 28-30 because your base salary has increased by 10%.

Lines 68-70 show each employee's type as a string. Every object in Java knows its own class and can access this information through thegetClassMethod that all classes inherit from the Object class. The getClass method returns an object of typeclass(from the java.lang package) which contains information about the object's type, including the class name. Line 70 calls the getClass method on the object to get its runtime class (that is, a Class object representing the object's type). then methodgetNameis called on the object returned by getClass to get the name of the class. For more information about the Class class, see the online documentation athttp://www.java.sun.com/javase/6/docs/api/java/lang/Class.html.

In the example above, we avoid several compiler errors by reducing an Employee variable to a BasePlusCommissionEmployee variable on lines 53-54. If you remove the cast operator ( BasePlusCommissionEmployee ) from line 54 and try to assign the currentEmployee employee variable directly to the BasePlusCommissionEmployee Employee variable, you will get a "Type mismatch" compiler error. This error indicates that the attempt to assign the object reference of the superclass 'commissionEmployee' to the subclass variable 'basePlusCommissionEmployee' is not allowed. The compiler avoids this mapping because a commissioner is no longer a base commissioner: theIt is aThe relationship only applies between the subclass and its superclasses, not vice versa.

Likewise, if lines 56, 57, and 60 used the currentEmployee superclass variable instead of the Employees subclass variable to call the subclass-only methods getBaseSalary and setBaseSalary, we would get a "cannot find symbol" compiler error for any of these methods. get lines. Attempting to invoke subclass-only methods on a superclass reference is not allowed. Whereas lines 56, 57 and 60 are executed only if the instance of line 49 returns true to indicate that a reference to a BasePlusCommissionEmployee object has been assigned. The compiler would throw errors on lines 56, 57, and 60 because getBaseSalary and setBaseSalary are not superclass methods and cannot be called on a superclass variable. Although the actual method invoked depends on the type of object at runtime, a variable can be used to invoke only those methods that are members of the type of the variable being checked by the compiler. When we use an employee superclass variable, we can call only the methods found in the employee class: Earnings, toString, and Employee'sto receivejFoundmethods.

10.5.7 Summary of allowed assignments between superclass and subclass variables

Now that you've seen a complete application that polymorphically processes multiple subclass objects, let's summarize what you can and cannot do with superclass and subclass objects and variables. Although it is also a subclass objectIt is asuperclass object, but the two objects are different. As discussed above, subclass objects can be treated as if they were superclass objects. However, because the subclass can have additional subclass-only members, assigning a superclass reference to a subclass variable without an explicit cast is not allowed; such an assignment would leave the subclass members undefined for the superclass object.

In the current section, as well as Section 10.3 and Chapter 9, we discuss four ways to assign superclass and subclass references to variables of superclass and subclass types:

  1. Assigning a superclass reference to a superclass variable is easy.
  2. Assigning a subclass reference to a subclass variable is easy.
  3. Assigning a subclass reference to a superclass variable is safe because the subclass objectIt is aObject of your upper class. However, this reference can be used to refer only to members of the superclass. If this code references subclass-only members via the superclass variable, the compiler will report errors.
  4. Attempting to assign a superclass reference to a subclass variable is a compiler error. To avoid this error, the superclass reference must be explicitly cast to a subclass type. If the object referenced by the reference is not a subclassed object at runtime, an exception will be thrown. (See Chapter 13 for more information on exception handling.) The instanceof operator can be used to ensure that such a cast is performed only if the object is a subclassed object.

10.6 Final Methods and Classes

We saw in Section 6.10 that variables can be declared final to indicate that they cannot be changed once initialized; such variables represent constant values. It is also possible to declare methods, method parameters and classes with the last modifier.

A method declared final in a superclass cannot be overridden in a subclass. Methods declared as private are implicitly final, as it is impossible to override them in a subclass. Statically declared methods are also implicitly final. The declaration of a final method can never change, so all subclasses use the same method implementation and calls to final methods are resolved at compile time; which is known asstatic connection🇧🇷 Because the compiler knows that final methods cannot be overridden, it can optimize programs by removing calls to final methods and replacing them with the extended code of their declarations at each position of the method call, a technique known asCole or code.

Performance tip 10.1

The compiler may decide to embed a final method call, and will do so for small, simple final methods. Injection does not violate encapsulation or information hiding, but it does improve performance by removing the overhead of a method call.

A class declared as final cannot be a superclass (that is, a class cannot extend a final class). All methods in a final class are implicitly final. The String class is an example of a final class. This class cannot be extended, so programs using Strings can rely on the functionality of String objects as specified in the Java API. Class finalization also prevents programmers from creating subclasses that can circumvent security restrictions. For more information about completion classes and methods, seehttp://www.java.sun.com/docs/books/tutorial/java/IandI/final.html🇧🇷 This page provides additional information on using final classes to improve the security of a system.

Common Programming Error 10.5

Attempting to declare a subclass of a final class is a compiler error.

Observation of software development 10.6

In the Java API, the vast majority of classes are not declared final. This allows for inheritance and polymorphism, the fundamental features of object-oriented programming. However, in some cases it is important to make classes final, usually for security reasons.

10.7 Case Study: Creating and Using Interfaces

Our next example (Figures 10.11 through 10.13) uses the payroll system from Section 10.5. Suppose the company in question wants to perform multiple accounting operations in a single accounts payable application. In addition to calculating the merit to be paid to each employee, the company must also calculate the pay due for each of the various accounts (ie, accounts payable). acquired goods). Although they refer to unrelated things (i.e. employees and invoices), both operations are related to receiving some kind of payment. In the case of an employee, wages refer to the employee's earnings. In the case of an invoice, payment is for the total cost of the goods listed on the invoice. Can we polymorphically compute things as disparate as employee payments and invoices in a single application? Does Java provide a feature that requires independent classes to implement a common set of methods (for example, a method that calculates the amount of a payment)? Javainterfacesprovide this skill.

Interfaces define and standardize the way things like people and systems can interact with each other. For example, a radio's controls serve as an interface between radio users and the radio's internal components. The controls only allow users to perform a limited set of operations (e.g., changing stations, adjusting volume, switching between AM and FM), and different radios may implement the controls in different ways (e.g., using buttons, dials, etc.) , voice control). 🇧🇷 commands). The specified interfacehe wasOperations that a radio must allow users to perform but are not specifiedHe wasoperations are performed. Likewise, the interface between a driver and a car with a manual transmission includes the steering wheel, gearshift lever, clutch pedal, accelerator pedal, and brake pedal. The same interface can be found on almost all manual transmission cars, so someone who knows how to drive a specific manual transmission car can drive almost any manual transmission car. Each car's components may look different, but their overall purpose is the same: to let people drive.

Software objects also communicate through interfaces. A Java interface describes a set of methods that can be invoked on an object, for example to instruct the object to perform a task or return information. The following example shows an interface called Payable to describe the functionality of any payable object and therefore must provide a method to determine the amount of payment due. ONEinterface declarationStart with the keywordinterfaceand contains only constants and abstract methods. Unlike classes, all interface members must be public, and interfaces must not specify implementation details such as concrete method declarations and instance variables. Therefore, all methods declared in an interface are implicitly public abstract methods, and all fields are implicitly public, static, and final.

Good Programming Practices 10.1

According to Chapter 9 of the Java Language Specification, it is appropriate to declare an interface's methods without the public and abstract keywords because they are redundant in interface method declarations. Likewise, constants must be declared without the public, static, and final keywords, as they are also redundant.

To use an interface, a concrete class must specify it.implementedthe interface and must declare each method on the interface with the signature specified in the interface declaration. A class that does not implement all interface methods is an abstract class and must be declared abstract. Implementing an interface is like signing a contract with the compiler that says, "I will either declare all methods specified by the interface, or declare my class as abstract."

Common Programming Error 10.6

If no methods of an interface are implemented in a concrete class that implements the interface, a compiler error will occur indicating that the class should be declared abstract.

An interface is typically used when different (ie, unrelated) classes need to share common methods and constants. This allows objects of unrelated classes to be processed polymorphically; Objects of classes that implement the same interface can respond to the same method calls. You can create an interface that describes the functionality you want and implement it in any class that requires that functionality. For example, in the Accounts Payable application developed in this section, we implement the Accounts Payable interface for any class that needs to be able to calculate a payment amount (for example, Employee, Invoice).

(Video) Chapter 10 Object Oriented Programming Polymorphism and Interfaces Part 3

An interface is often used instead of an abstract class when there is no default implementation to inherit from, that is, there are no default fields or method implementations. Interfaces are usually public types, so they are usually declared in files with the same name as the interface and a .java file name extension.

10.7.1 Development of a payment hierarchy

To create an application that can determine employee payments and invoices, let's first create the Payable interface that contains the getPaymentAmount method that returns a duplicate amount to be paid by an object of any class that implements the interface. The getPaymentAmount method is a general-purpose version of the employee hierarchy income method: the income method calculates a specific pay amount for an employee, while getPaymentAmount can be applied to a variety of unrelated objects. After declaring the Payable interface, let's introduce the Invoice class that implements the Payable interface. Next, we modify the Employee class so that it also implements the Payable interface. Finally, we update the SalaryEmployees employee subclass to "fit" the pay hierarchy (that is, we rename the SalaryEmployees revenue method to getPaymentAmount).

Good Programming Practices 10.2

When declaring a method on an interface, choose a method name that broadly describes the purpose of the method, as the method can be implemented by many independent classes.

The Invoice and Employee classes represent things for which the company must be able to calculate a payment amount. Both classes implement Payable, so a program can call the getPaymentAmount method on the Invoice and Employee objects in the same way. As we'll see below, this allows for polymorphic processing of invoices and employees needed for our company's accounts payable.

The UML class diagram inFigure 10.10shows the hierarchy used in our Accounts Payable application. The hierarchy starts with the accounts payable interface. The UML distinguishes an interface from other classes by enclosing the word "interface" in guillotines (« and ») above the interface name. The UML expresses the relationship between a class and an interface through a relationship called a realization. A class is intended to "realize" or implement the methods of an interface. A class diagram models an implementation as a dashed arrow with an empty arrowhead pointing from the implementation class to the interface. The diagram inFigure 10.10indicates that the Invoice and Employee classes realize (that is, implement) the Payable interface. Note that, as in the class diagram ofFigure 10.2, the Employee class is italicized, indicating that it is an abstract class. The concrete class "SaliedEmployee" extends "Employee" and inherits its superclass's realization relationship with the "Payable" interface.

Chapter 10: Object Oriented Programming: Polymorphism (4)

Figure 10.10 UML class diagram of payable interface hierarchy.

10.7.2 Declaration of the paid interface

The Payable interface declaration begins at line 4 of Figure 10.11, which contains the public abstract method getPaymentAmount (line 6). Note that the method is not explicitly declared public or abstract. Interface methods must be public and abstract, so they don't need to be declared as such. Interface Payable has only one method: Interfaces can have any number of methods. (We'll see the term "markup interfaces" later in this book; they don't actually have any methods. In fact, a markup interface doesn't contain constant values ​​either; it just contains an empty interface declaration.) getPaymentAmount method has no parameters, but interface methods can have parameters.

1 //Figure 10.11 Payable.java2 //Payable interface declaration.34 public interfaceTurn off5{6 erm goodgetPagamentoValor();//calculate the payment; no reaction7}//payable end interface

Figure 10.11 Payable Interface Declaration.

10.7.3 Create Class Invoice

We now create the Invoice class (Figure 10.12) to represent a simple invoice that contains invoice information for a single type of part. The class declares private instance variables partNumber, partDescription, Quantity, and pricePerItem (on lines 6-9) that specify the part number, a description of the part, the quantity of the part ordered, and the price per item. Class Invoice also contains a constructor (line 12-19),to receivejFoundMethods (lines 22-67) that manipulate the class's instance variables, and a toString method (lines 70-75) that returns a String representation of an Invoice object. Note that methods setQuantity (lines 46-49) and setPricePerItem (lines 58-61) ensure that Quantity and PricePerItem are only given non-negative values.

1 //Figure 10.12: Invoice.java2 //A classe Invoice implementa Payable.34 public classinvoiceimplementedTurn off5{6 Private lineItem number;7 Private linePartial description;8 internal privateCrowd;9 doubly privatePrice per piece;1011 //Constructor with four arguments12 AdvertisingInvoice(linePaper,lineDesignation,e Tto say,13 erm goodPreis)14{fifteenpart number = part;sixteenpartDescription = description;17setAmount(count);//Validate and save the quantity18setPricePerItem( price );//validate and save the price per item19}//Exit four-argument arithmetic constructor2021 //Set part number22 public voidstable part number(linePaper )23{24part number = part;25}//final method setPartNumber2627 //get the part number28 Advertising linegetPartNumber()29{30 give backItem number;31}//Method final getPartNumber3233 //set description34 public voidsetPartDescription(linedesignation)35{36partDescription = description;37}//last method setPartDescription3839 //description received40 Advertising linegetPartDescription()41{42 give backPartial description;43}//Método final getPartDescription4445 //determine the amount46 public voidsetMenge(e Tto say )47{48value = (number <0) ?0: to say;//quantity cannot be //Negative49}//final method setMenge5051 //get amount52 international audiencegetAmount()53{54 give backCrowd;55}//last method getQuantity5657 //Fixed price per item58 public voidsetPricePerItem(erm goodPreis)59{60Price per item = ( Price <0.0) ?0.0: Preis;//validate price61}//last method setPricePerItem6263 //Get price per item64 doubly publicgetPricePerItem()Sixty-five{66 give backPrice per piece;67}//last method getPricePerItem6869 //returns the string representation of the Invoice object70 Advertising lineChain()71{72 give back line.Format("%s: \n%s: %s (%s) \n%s: %d \n%s: $%,.2f",73 "Invoice","item number", getPartNumber(), getPartDescription(),74 "Crowd", getAmount(),"Price per item", getPricePerItem() );75}//final toString method7677 //Method required to fulfill the contract with the Pay interface78 Advertising erm goodgetPaymentAmount()79{80 give backgetQuantity() * getPricePerItem();//Calculate Total Cost81}//Método final getPaymentAmount82}//last class calculation

Figure 10.12 Invoice class implementing Payable.

Line 4 of Figure 10.12 shows that the Invoice class implements the Payable interface. Like all classes, the Invoice class implicitly extends Object. Java does not allow subclasses to inherit from more than one superclass, but it does allow a class to inherit from a superclass and implement more than one interface. In fact, a class can implement as many interfaces as it needs, in addition to extending another class. To implement more than one interface, use a comma-separated list of interface names after the implements keyword in the class declaration, as in:

Advertising classEstender ClassName Implementar SuperclassName FirstInterface, SecondInterface, 。ヲ

All objects of a class that implement multiple interfaces have an is-one relationship with each implemented interface type.

Class Invoice implements the only method on the Payable interface. Method getPaymentAmount is declared on lines 78-81. The method calculates the total payment required to pay the invoice. The method multiplies the quantity and price values ​​per item (obtained by the correspondingto receivemethods) and returns the result (line 80). This method fulfills the implementation requirement for this method in the Payable interface: we fulfill the interface contract with the compiler.

10.7.4 Modifying the employee class to implement the paid interface

Now let's modify the Employee class to implement the Payable interface. Figure 10.13 contains the modified Employee class. This class declaration is identical to the one in Figure 10.4, with two exceptions. First, line 4 of Figure 10.13 shows that the Employee class now implements the Payable interface. Second, since Employee now implements the Payable interface, we need to rename the earnings to getPaymentAmount throughout the Employee hierarchy. However, as with the Earnings method in the Employee class version in Figure 10.4, there is no point in implementing the getPaymentAmount method in the Employee class, as we cannot calculate the salary payment owed to a general Employee; We must first know the specific type of employee. 🇧🇷 For this reason, in Figure 10.4, we declared the method gains abstractly, and as a result, the Employee class had to be declared abstractly. This forced every subclass of employees to replace gains with a concrete implementation.

1 //Figure 10.13 Employee.java2 //The abstract superclass Employee implements Pay.34 AdvertisingabstractclassemployeeimplementedTurn off5{6 Private lineFirst name;7 Private lineLast name;8 Private linesocial Security number;910 //Constructor with three arguments11 AdvertisingEmployee(lineFirst,linelast,linesn)12{13firstname = first;14lastname = lastname;fifteenCPF = ssn;sixteen}//Exit employee constructor with three arguments1718 //Enter the name19 public voidEnter the name(lineFirst )20{21firstname = first;22}//last method setFirstName2324 //return the name25 Advertising linegetFirstName()26{27 give backFirst name;28}//last method getFirstName2930 //set surnames31 public voidestablecerApellido(linelast )32{33lastname = lastname;34}//last method setLastName3536 //return last name37 Advertising linegetLastName()38{39 give backLast name;40}//last method getLastName4142 //Set social security number43 public voidsetNúmeroSeguridadSocial(linesn)44{45CPF = ssn;//must validate46}//last method setSocialSecurityNumber4748 //Return social security number49 Advertising linegetSocialSecurityNumber()50{51 give backsocial Security number;52}//last getSocialSecurityNumber method5354 //return Stringdarstellung des Employee-Objekts55 Advertising lineChain()56{57 give back line.Format("%s %s\nSocial Security Number: %s",58getFirstName(), getLastName(), getSocialSecurityNumber());59}//final toString method6061 //Note: We do not implement the getPaymentAmount payment method //here like this62 //This class must be declared as abstract to avoid compilation //Mistake.63}//terminate the Employee abstract class

Figure 10.13 Class Employee implementing Payable.

In Figure 10.13 we handle this situation differently. Remember that when a class implements an interface, the class makes a contract with the compiler declaring that the class implements each of the interface's methods, or that the class is declared abstract. If the latter option is chosen, we don't need to declare the interface methods in the abstract class as abstract; they are already implicitly declared as such in the interface. Each concrete subclass of the abstract class must implement the interface methods to fulfill the superclass's contract with the compiler. If the subclass does not do this, it must also be declared abstract. As indicated in the comments on lines 61-62, the Employee class in Figure 10.13 does not implement the getPayAmount method, so the class is declared abstract. Any direct subclass of Employee inherits the superclass's contract to implement the getPaymentAmount method, and therefore must implement this method to become a concrete class in which objects can be instantiated. A class that extends one of the concrete subclasses of Employee inherits an implementation of getPaymentAmount and is therefore also a concrete class.

10.7.5 Changing the salary class for use in the supplier hierarchy

Figure 10.14 contains a modified version of the SalaryEmployee class that extends Employee and respects the superclass Employee contract to implement the Payable interface's getPaymentAmount method. This version of SalaryEmployee is identical to Figure 10.5, except that the version here implements the getPayAmount method (lines 30-33) instead of the Earnings method. The two methods contain the same functionality but have different names. Remember that the Payable version of the method has a more generic name to be applicable to potentially different classes. The remaining Employee subclasses (such as HourlyEmployee, CommissionEmployee, and BasePlusCommissionEmployee) should also be changed to contain method getPaymentAmount instead of Revenue to reflect the fact that Employee now implements Payable. We'll leave these changes as an exercise and only use employees in our testing program in this section.

1 //Figure 10.14: SalaryEmployee.java2 //Class SalariedEmployee extends Employee, which implements Payable.34 public classpaid employeeexpandedemployee5{6 doubly privateweekly salary;78 //Constructor with four arguments9 AdvertisingPaid employee (lineFirst,linelast,linesn,10 erm goodWage)11{12 super(first, last, ssn);//Switch to Employee Builder13setWeeklySalary(salary);//Validate and save salary14}//Complete salaried employee constructor with four argumentsfifteensixteen //fixed salary17 public voidestablecerSalarioSemanal(erm goodWage)18{19Weekly salary = salary <0.0?0.0: Wage;20}//last method definedWeeklySalary2122 //salary back23 doubly publicgetWeeklySalary()24{25 give backweekly salary;26}//Method final getWeeklySalary2728 //calculate yield; Implement the payment method interface that was29 //Summary in the Employee superclass30 doubly publicgetPaymentAmount()31{32 give backgetWeeklySalary();33}//Método final getPaymentAmount3435 //returns the string representation of the SalaryEmployee object36 Advertising lineChain()37{38 give back line.Format("Employee: %s\n%s: $%,.2f",39 super.Chain(),"weekly wage", getWeeklySalary() );40}//final toString method41}//Employed graduation class

Figure 10.14 Class Salary, which implements the interface of the Payable method getPaymentAmount.

If a class implements an interface, the same is true.It is athe relationship provided by inheritance is applied. For example, the class implements Employee Pay, so we can say that an EmployeeIt is aDelete. In fact, objects of any class that extend Employee are also Payable objects. For example, SalaryEmployee objects are Payable objects. As with inheritance relationships, an object of a class that implements an interface can be thought of as an object of type interface. Objects of any subclass of the class that implements the interface can also be considered objects of type interface. So, just as we can assign a SalaryEmployee object reference to a parent Employee variable, we can assign a SalaryEmployee object reference to a Payable interface variable. Invoice implements Payable, just like an Invoice objectIt is aPayable object and we can assign the reference of an Invoice object to a Payable variable.

Software Engineering Note 10.7

Inheritance and interfaces are similar in their implementation of the is-a relationship. An object of a class that implements an interface can be thought of as an object of that interface type. An object of any subclass of a class that implements an interface can also be thought of as an object of type interface.

Software Engineering Observation 10.8

The is-one relationship that exists between superclasses and subclasses, and between interfaces and the classes that implement them, applies when an object is passed to a method. When a method parameter receives a variable of type superclass or interface, the method polymorphically processes the object received as an argument.

Software Development Note 10.9

Using a superclass reference, we can polymorphically invoke any method specified in the superclass declaration (and in the object class). Using an interface reference, we can polymorphically invoke any method specified in the interface declaration (and in the Object class, because a variable of an interface type must refer to an object to invoke methods, and all objects have methods of the Object class included) ) .

10.7.6 Using the payment interface for polymorphic processing of invoices and employees

PayableInterfaceTest (Figure 10.15) illustrates that the Payable interface can be used to polymorphically process a set of invoices and employees within a single application. Line 9 declares PayableObjects and assigns it an array of four Payable variables. Lines 12 and 13 map the Invoice object references to the first two elements of paidObjects. Lines 14-17 then assign the SalaryEmployee object references to the remaining two members of payObjects. These allowances are allowed because an invoice is an employee responsibilityIt is aemployee and an employeeesone Payable. Lines 23-29 use the extended for statement to turn each Payable object into payableObjects and output the object as a string along with the payment amount due. Note that line 27 calls the toString method of a Payable interface reference, even though toString is not declared on the Payable interface: all references (including those of interface types) point to objects that extend Object and therefore have a toString method . (Note that toString can also be called implicitly here.) Line 28 calls the pay method getPaymentAmount to retrieve the payment amount for each object in payObjects , regardless of the object's actual type. The output shows that the method calls in lines 27-28 invoke the implementation of the corresponding class's toString and getPaymentAmount methods. For example, if currentEmployee refers to an invoice during the first iteration of the for loop, the Invoice class's toString and getPaymentAmount are executed.

Software Engineering Note 10.10

All methods of the Object class can be called using a reference to an interface type. A reference points to an object, and all objects inherit methods from the Object class.

1 //Figure 10.15: PayableInterfaceTest.java2 //Chargeable test interface.34 public classpayment interface test5{6 AdvertisingstaticFileDirector(lineArguments[] )7{8 //Create a payment matrix with four elements9Items to be paid to be paid[] =neuTurn off[4];1011 //Populate the array with objects that implement Payable12payable item[0] =neuInvoice("01234","Seat",2,375.00);13payable item[1] =neuInvoice("56789","Tires",4,79.95);14payable item[2] =fifteen neuPaid employee ("John","Herrero","111-11-1111",800.00);sixteenpayable item[3] =17 neuPaid employee ("lisa","Barnes","888-88-8888",1200.00);1819System.Fora.println(20 "Invoices and employees processed polymorphically:\n");2122 //process each element in array of payObjects generically23 through the(Payable currentPayable: payObjects)24{25 //currentPagable output and its corresponding payment amount26System.Fora.printf("%s\n%s: $%,.2f\n\n",27pagoActual.toString(),28 "Pay day", actualPayable.getPaymentAmount() );29}//finish with30}//last main31}//ultimate class payment interface test

PRODUCTION

Invoices and employees polymorphically processed:Invoice:Part Number:01234(Seat) Quantity:2Price per piece: $375.00Payment due: $750.00Invoice: Part number:56789(Tyres) Quantity:4Price per piece: $79.95Payment due: $319.80Employee: John Smith Social Security Number: 111-11-1111 Weekly Salary: $800.00Payment due: $800.00Employee: Lisa Barnes Social Security Number: 888-88-8888 Weekly Salary: $1.200.00payment due: $1,200.00

Figure 10.15 Payment interface test program processing invoices and employees polymorphically.

10.7.7 Declaration of constants in interfaces

As already mentioned, an interface can declare constants. Constants are implicitly public, static, and final; Again, these keywords are not required in the interface declaration. A popular use of an interface is to declare a set of constants that can be used in many class declarations. Consider the interface constants:

public interfaceconstants {e TLIKE =1;e TDOS =2;e TTHREE =3; }

A class can use these constants by importing the interface and referencing each constant as Constants.ONE, Constants.TWO, and Constants.THREE. Note that if a class uses a static import statement (introduced in Section 8.12) to import the interface, it can only refer to the imported constants by their names (that is, ONE, TWO, and THREE).

Note of Software Development 10.11

As of Java SE 5.0, it has become a programming best practice to create arrays of constants as enumerations using the enum keyword. See Section 6.10 for an introduction to enumeration and Section 8.9 for more details on enumeration.

10.7.8 General Java API Interfaces

In this section, we review several common interfaces found in the Java API. The power and flexibility of interfaces are used extensively throughout the Java API. These interfaces are implemented and used in the same way as the interfaces you create (for example, the Payable interface in Section 10.7.2). As you will see in this book, the Java API interfaces allow you to use your own classes within the frameworks provided by Java, for example, customizing objects of your own types and creating tasks that can run concurrently with other tasks on the same program. Figure 10.16 provides a brief overview of some of the more popular Java API interfaces.

interface

Description

Comparable

As you learned in Chapter 2, Java includes several comparison operators (such as <, <=, >, >=, ==, !=) that you can use to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to compare objects of a class that implements the interface. The interface includes a method, CompareTo, which compares the object calling the method with the object passed as an argument to the method. Classes must implement CompareTo to return a value indicating whether the object being called on is less than (returns negative integer), equal to (returns 0), or greater than (returns positive integer) the object passed as an argument, using any criteria specified by the programmer. For example, if the Employee class implements Comparable, its CompareTo method can compare Employee objects based on their profit values. Interface Comparable is often used to sort objects in a collection, for example B. an array used. We use Comparable in Chapter 15, Generics, and Chapter 16, Collections.

serializable

An interface used to identify classes whose objects can be written (that is, serialized) or read (that is, deserialized) or transmitted over a network by a type of storage (eg, disk file, database array). We use Serializable in Chapter 14, Files and Streams, and Chapter 19, Networks.

Executable

Implemented by any class for which objects of that class can run in parallel using a technique called multithreading (discussed in Chapter 18, Multithreading). The interface includes a method, execute, which describes the behavior of an object when it is executed.

GUI event listener interfaces

You work with graphical user interfaces (GUI) on a daily basis. For example, in your web browser, you can enter the address of a website to visit in a text field or click a button to return to a previously visited website. When you enter a website address or click a button in your web browser, the browser should respond to your interaction and perform the desired task for you. Their interaction is called an event, and the code the browser uses to respond to an event is called an event handler. In Chapter 11, GUI Components: Part 1, and Chapter 17, GUI Components: Part 2, you will learn how to create Java GUIs and how to create event handlers to respond to user interactions. Event handlers are declared in classes that implement an appropriate event listener interface. Each event listener interface specifies one or more methods that must be implemented to respond to user interactions.

oscillating constants

Contains constants used in GUI programming to position GUI elements on the screen. We looked at GUI programming in Chapters 11 and 17.

Figure 10.16: General Java API Interfaces.

10.8 (Optional) Software development case study: Integrating legacy into the ATM system

We are now reviewing our ATM system design to see how it could benefit from legacy. To apply inheritance, we first look for common elements between classes in the system. We created an inheritance hierarchy to model similar (but not identical) classes more elegantly and efficiently. We then modified our class diagram to include the new inheritance relationships. Finally, we demonstrate how our updated design is translated into Java code.

In Section 3.9 we encountered the problem of representing a financial transaction in the system. Rather than creating one class to represent all transaction types, we decided to create three individual transaction classes (balance inquiry, withdrawal, and deposit) to represent the transactions the ATM system can perform.Figure 10.17Shows the attributes and operations of the Balance Inquiry, Payment and Deposit classes. Note that these classes share an attribute (account number) and an operation (execution). Each class requires the accountNumber attribute to indicate the account to which the transaction applies. Each class contains an execution operation that the ATM calls to complete the transaction. Clearly display balance inquiries, disbursements and depositsThe typeProtocol.Figure 10.17shows similarities between the transaction classes, so that the use of inheritance to account for common characteristics for the design of the “balance inquiry”, “withdrawal” and “deposit” classes seems appropriate. We put the common functionality into a superclass, Transaction, which is extended by the Balance Inquiry, Withdrawal, and Deposit classes.

(Video) Chapter10 Object Oriented Programming Polymorphism and Interfaces Part 4

Chapter 10: Object Oriented Programming: Polymorphism (5)

Figure 10.17 Attributes and operations of the Balance Inquiry, Withdrawal and Deposit classes.

The UML specifies a relationship called generalization to model inheritance.Figure 10.18is the class diagram that models the generalization of the Transaction superclass and the Balance Inquiry, Withdrawal, and Deposit subclasses. Arrows with hollow triangular heads indicate that the Balance Inquiry, Withdrawal, and Deposit classes extend the Transaction class. The Transaction class is intended to be a generalization of the Balance Inquiry, Withdrawal, and Deposit classes. The Balance Inquiry, Withdrawal and Deposit classes are considered specializations of the Transaction class.

The Balance Inquiry, Withdrawal, and Deposit classes all share the account number integer attribute, so we remove that shared attribute and put it in the Transaction superclass. We no longer list the account number in the second compartment of each subclass, as all three subclasses inherit this transaction attribute. However, remember that subclasses cannot access the private attributes of a superclass. Therefore, we include the public method getAccountNumber in the Transaction class. Each subclass inherits this method, so the subclass can access your account number to complete a transaction if needed.

CorrespondingFigure 10.17, the CheckBalance, Withdrawal and Deposit classes share the execution of the operation, so we decided that the superclass Transaction should contain the execution of the public method. However, it makes no sense to implement execution in the Transaction class, as the functionality this method provides depends on the actual transaction type. Therefore, we declare the execute method in the Transaction superclass as abstract. Any class that contains at least one abstract method must also be declared abstract. This forces any subclass of Transaction that should be a concrete class (that is, balance inquiry, payment, and deposit) to implement the execute method. The UML requires that we italicize the names of abstract classes (and abstract methods), so the Transaction and its execution method appear in italicsFigure 10.18🇧🇷 Note that method execution in the Balance Inquiry, Withdrawal, and Deposit subclasses is not shown in italics. Each subclass replaces the superclass's transaction execution method with a concrete implementation that performs the appropriate steps to complete that type of transaction. Notice thatFigure 10.18contains the execution of the operation in the third compartment of the balance, payment and deposit inquiry classes, as each class has a different concrete implementation of the overwriting procedure.

Adding inheritance gives the ATM an elegant way to do all transactions "generally". For example, let's say a user wants to perform an account balance inquiry. ATM sets a transaction reference to a new object of class BalanceInquiry. When ATM uses its transaction reference to call the execute method, the execution version of BalanceInquiry is called.

This polymorphic approach also makes the system easily extensible. If we wanted to create a new transaction type (for example, bank transfer or bill payment), we would simply create an additional transaction subclass that replaces the execution method with a method version suitable for executing the new transaction type. We would only need to make minimal changes to the system code to allow users to select the new transaction type from the main menu and to allow the ATM to instantiate and run objects of the new subclass. The ATM can execute transactions of the new type using the current code, as it polymorphically executes all transactions using a common transaction reference.

Chapter 10: Object Oriented Programming: Polymorphism (6)

Figure 10.18 Class diagram modeling the generalization of the Transaction superclass and the Balance Inquiry, Withdrawal, and Deposit subclasses. Note that abstract class names (for example, Transaction) and method names (for example, execute in Transaction class) appear in italics.

An abstract class like Transaction is one for which the programmer never tries to instantiate objects. An abstract class simply declares attributes and behaviors common to its subclasses in an inheritance hierarchy. The Transaction class defines the concept of what it means to be a transaction that has an account number and is executed. You might be wondering why we bother putting the abstract method execution in the Transaction class when a concrete implementation is missing. Conceptually, we include this method because it corresponds to the defining behavior of all transactions: execution. Technically, we need to put method execution in the Transaction superclass so that ATM (or any other class) can polymorphically invoke the overridden version of that method from any subclass via a transaction reference. Furthermore, from a software development perspective, putting an abstract method in a superclass forces the subclass implementer to override that method with concrete implementations in the subclasses, or the subclasses also become abstract, preventing the objects of the subclasses from being instantiated.

The Balance Inquiry, Withdrawal and Deposit subclasses inherit the account number attribute from the Transaction superclass, but the Withdrawal and Deposit classes contain the additional quantity attribute that distinguishes them from the Balance Inquiry class. Withdrawal and Deposit classes require this additional attribute to store the amount of money that the user wants to withdraw or deposit. The BalanceInquiry class does not need such an attribute and only requires an account number to run. Although two of the three Transaction subclasses share this attribute, we don't put it in the Transaction superclass; we put only features common to all subclasses in the superclass; Otherwise, subclasses may inherit attributes (and methods) that they don't need and shouldn't have.

Figure 10.19features an updated class diagram of our model that includes inheritance and introduces the Transaction class. We model an association between the ATM class and the transaction class to show whether the ATM is executing a transaction at a given time or not (i.e. there are zero or one transaction objects in the system at the same time). Since a cashout is a transaction type, we no longer draw a line of association directly between the ATM class and the cashout class. The Payout subclass inherits the transaction mapping from the superclass to the ATM class. The Balance and Deposit Query subclasses also inherit this mapping, so the previously omitted mappings between the ATM and the Balance and Deposit Query classes also do not exist.

Chapter 10: Object Oriented Programming: Polymorphism (7)

Figure 10.19 ATM system class diagram (with inheritance). Note that abstract class names (eg, Transaction) appear in italics.

We also added an association between the Transaction class and the BankDatabase (Figure 10.19🇧🇷 All transactions require a reference to the BankDatabase in order to access and change account information. Since every Transaction subclass inherits this reference, we no longer model the mapping between the Withdrawal class and BankDatabase. Likewise, the previously omitted associations between BankDatabase and the BalanceInquiry and Deposit classes no longer exist.

We show an association between the Transaction class and the screen. All transactions show the user the output through the screen. Therefore, we no longer include the association previously modeled between Cashier and Screen, although Cashier still participates in associations with ATM and Keyboard. Our class diagram, which includes inheritance, also models Deposit and BalanceInquiry. We show associations between Deposit and DepositSlot and Keypad. Note that the Balance Inquiry class is not part of any association beyond the one inherited from the Transaction class: a balance inquiry only needs to interact with the database and the bank's screen.

The class diagram in Figure 8.21 shows attributes and operations with visibility flags. We now present a modified class diagram that integrates inheritance intoFigure 10.20🇧🇷 This abbreviated diagram does not show the inheritance relationships, but it does show the attributes and methods after we use inheritance in our system. To save space, as in Figure 4.16, we have not included the attributes that indicate associations inFigure 10.19– However, we include them in the Java implementation in Appendix H. We also omit all parameters from the operation, as we did in Figure 8.21 - adding inheritance does not affect the parameters already modeled in Figure 8.21. 6.27-6.30.

Chapter 10: Object Oriented Programming: Polymorphism (8)

Figure 10.20 Diagram of classes with attributes and operations (with inheritance). Note that abstract class names (for example, Transaction) and method names (for example, execute in Transaction class) appear in italics.

Observation of software development 10.12

A complete class diagram shows all associations between classes and all attributes and operations for each class. When the number of class attributes, methods and associations is significant, a good practice to promote readability is to separate this information into two class diagrams: one focused on associations and the other on attributes and methods.

Implement the ATM (Incorporation Legacy) system design

In Section 8.18 we begin to implement the ATM system design. Now we'll modify our implementation to include inheritance, using the Withdrawal class as an example.

  1. If class A is a generalization of class B, then class B extends class A in the class declaration. For example, the abstract superclass Transaction is a generalization of the Withdrawal class. Figure 10.21 contains the shell of the Withdrawal class, which contains the appropriate class declaration.
  2. If class A is an abstract class and class B is a subclass of class A, then class B must implement the abstract methods of class A if class B is a concrete class. For example, the Transaction class contains an abstract execution method, so if we want to instantiate a Withdrawal object, the Withdrawal class must implement this method. Figure 10.22 is the Java code for the Withdrawal class.Figure 10.19and Figure 10.20. The Withdrawal class inherits the Transaction superclass's account number field, so Withdrawal does not need to declare this field. The Withdrawal class also inherits Screen and BankDatabase references from its Transaction superclass, so we don't include those references in our code.Figure 10.20specifies the attribute value and operation execution on the Withdrawal class. Line 6 of Figure 10.22 declares a field for attribute quantity. Lines 16-18 declare the shell as the method to perform the operation. Remember that the Withdrawal subclass must provide a concrete implementation of the abstract execute method in the Transaction superclass. The keyboard and ATM references (lines 7 and 8) are fields derived from the withdrawal mappings inFigure 10.19🇧🇷 [Note: The constructor in the fully functional version of this class initializes these references to real objects.]
1 //Class withdrawal represents an ATM withdrawal transaction2 public classwithdrawalexpandedtransaction3{4}//end of class withdrawal

Figure 10.21 Java code for the shell of the Withdrawal class.

1 //Retiro.java2 //Generated using the class diagrams in Figure 10.21 and Figure 10.223 public classwithdrawalexpandedtransaction4{5 //Attribute6 doubly privateCrowd;//amount to withdraw7 Privatenumeric keyboard;//keyboard reference8 PrivateATM ATM;//ATM reference910 //constructor without arguments11 AdvertisingWithdrawal()12{13}//Exit retraction constructor with no arguments14fifteen //Execute Method Overridessixteen public voidcorre()17{18}//final execution of the method19}//end of class withdrawal

Figure 10.22 Java code for the Withdrawal class based onfigs 10.19j10.20.

Software Development Note 10.13

Several UML modeling tools convert UML-based designs into Java code and can significantly speed up the implementation process. For more information about these tools, see the web resources listed at the end of Section 2.8.

Congratulations on completing the design portion of the case study! We fully implement the ATM system in 670 lines of Java code in Appendix H. We recommend that you read the code and its description carefully. The code is heavily commented and follows exactly the layout you already know. The accompanying description has been carefully written to help you understand the implementation based on the UML design. Mastering this code is a wonderful culmination after studying Chapters 1-8.

Self-Assessment Exercises for Software Development Case Studies

10.1The UML uses an arrow with __________________ to indicate a generalization relationship.

  1. solid arrowhead
  2. triangular hollow arrowhead
  3. diamond shaped hollow arrowhead
  4. arrow tip

10.2Indicate whether the following statement is true or false, and if false, explain why: The UML requires that we underline the abstract names of classes and methods.

10.3Write Java code to start implementing the layout for the transaction class specified infigs 10.19j10.20🇧🇷 Be sure to include private reference type attributes based on transaction class mappings. Also, be sure to include public getter methods that provide access to all the private attributes that subclasses need to do their jobs.

Answers to self-assessment exercises for the software development case study

10.1b.

10.2false. UML requires that we italicize abstract class names and method names.

10.3The design for the Transaction class produces the code shown in Figure 10.23. The bodies and methods of the class constructor are completed in Appendix H. When fully implemented, the getScreen and getBankDatabase methods will return the screen private reference attribute of the superclass Transaction and bankDatabase, respectively. These methods allow transaction subclasses to access the ATM screen and interact with the bank's database.

1 //The abstract transaction class represents an ATM transaction2 Advertisingabstractclasstransaction3{4 //Attribute5 internal privateAccount number;//indicates the affected account6 Privatedisplay screen;//ATM screen7 PrivateBankdatenbank Bankdatenbank;//Account information database89 //No-argument constructor called by subclasses with super()10 AdvertisingTransaction()11{12}//Exit transaction constructor with no arguments1314 //return account numberfifteen international audiencegetAccountNumber()sixteen{17}//Método final getAccountNumber1819 //return the reference to the screen20 Advertisingtela getScreen()21{22}//Method final getScreen2324 //returns the reference to the database of the bank25 AdvertisingBankDatabase getBankDatabase()26{27}//last method getBankDatabase2829 //abstract method replaced by subclasses30 AdvertisingabstractFilecorre();31}//top class transaction

Figure 10.23 Java Code for the Transaction-Based Classfigs 10.19j10.20.

10.9 Summary

This chapter introduced polymorphism: the ability to process objects that share the same superclass in a class hierarchy as if they were all objects of the superclass. The chapter discussed how polymorphism makes systems extensible and maintainable, and then showed how to use overriding methods to achieve polymorphic behavior. We introduce abstract classes that allow programmers to provide a suitable superclass from which other classes can inherit. You learned that an abstract class can declare abstract methods that each subclass must implement to become a concrete class, and that a program can use variables of an abstract class to polymorphically invoke implementations of abstract methods from subclasses. You also learned how to determine an object's type at runtime. Finally, the chapter covered declaring and implementing an interface as another way to achieve polymorphic behavior.

(Video) Chapter 10 Polymorphism via Interface

By now you should be familiar with classes, objects, encapsulation, inheritance, interfaces, and polymorphism, the most important aspects of object-oriented programming. In the next chapter, we'll delve into graphical user interfaces (GUIs).

This member has not yet provided a biography. Assuming it's interesting and varied and probably has something to do with programming.

Videos

1. 4.7: Introduction to Polymorphism - The Nature of Code
(The Coding Train)
2. Object-oriented Programming in 7 minutes | Mosh
(Programming with Mosh)
3. Chapter 10: Polymorphism (Part-1)
(Dr. On Wheels)
4. Chapter 10: Interfaces and Polymorphism
(Kianoosh G. Boroojeni)
5. Object Oriented Programming 9 –Polymorphism
(Computer Science)
6. Inheritance and Polymorphism in C++ - Horstmann, Chapter 10
(Camp Insights)
Top Articles
Latest Posts
Article information

Author: Dong Thiel

Last Updated: 21/03/2023

Views: 6037

Rating: 4.9 / 5 (79 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Dong Thiel

Birthday: 2001-07-14

Address: 2865 Kasha Unions, West Corrinne, AK 05708-1071

Phone: +3512198379449

Job: Design Planner

Hobby: Graffiti, Foreign language learning, Gambling, Metalworking, Rowing, Sculling, Sewing

Introduction: My name is Dong Thiel, I am a brainy, happy, tasty, lively, splendid, talented, cooperative person who loves writing and wants to share my knowledge and understanding with you.