9.5 Functionality of Object-Oriented Languages

As you might guess from the earlier discussion of object-oriented design, the basic construct in an object-oriented language is the class. In addition to looking at the class construct in this section, we examine the three essential ingredients in an object-oriented language: encapsulation, inheritance, and polymorphism. These ingredients foster reuse, thereby reducing the cost of building and maintaining software.

Encapsulation

In Chapter 7, we talked about important threads running through the discussion of problem solving. Two of these threads were information hiding and abstraction. Recall that information hiding is the practice of hiding the details of a module with the goal of controlling access to the details. We said in Chapter 7 that abstraction was a model of a complex system that includes only the details essential to the viewer. We defined three types of abstraction, but the definitions of each began and ended with the words “The separation of the logical view of . . . from its implementation details.” Abstraction is the goal; information hiding is a technique used to achieve the goal.

In the discussion of object-oriented design, we said that encapsulation is the bundling of data and actions in such a way that the logical properties of the data and actions remain separate from the implementation details. Another way of saying this is that encapsulation is a language feature that enforces information hiding. A module’s implementation is hidden in a separate block with a formally specified interface. An object knows things about itself, but not about any other object. If one object needs information about another object, it must request that information from that object.

The construct used to provide encapsulation is the class. Just as the concept of the class dominates object-oriented design, so the class concept is the major feature of Java and other object-oriented languages. Unfortunately, the related definitions are not standard across the phases of design and implementation. In the design (problem-solving) phase, an object is a thing or entity that makes sense within the context of the problem. In the implementation phase, a class is a language construct that is a pattern for an object and provides a mechanism for encapsulating the properties and actions of the object class.

Classes

Syntactically, a class is like a record in that it is a heterogeneous composite data type. However, records have traditionally been considered passive structures; only in recent years have they had subprograms as fields. The class, by contrast, is an active structure and almost always has subprograms as fields. The only way to manipulate the data fields of a class is through the methods (subprograms) defined in the class.

Here is how we might define class Person, based on one developed earlier:

FIGURE 9.4 visualizes class Person. The variable fields are blank. The subprograms are orange to indicate that they do not contain values but are subprograms.

A figure represents the class “Person.” The top three are the variable fields, labeled: name, email, and telephone. Fields from 4 to 8 are the subprograms, labeled: Initialize, Print, GetName, GetTelephone, and GetEmail.

FIGURE 9.4 Class Person

In our algorithms, we have used identifiers for simple variables and arrays without worrying about where they come from. If we use an identifier to represent a class, however, we must explicitly ask for the class to be created before we can use it. That is, we have to instantiate the class by using the new operator to get an object that fits the pattern. This operator takes the class name and returns an instance of the class. This algorithm instantiates a class Person, gets an object aPerson of the class, and stores and retrieves values in the object. We first instantiate a Name object but assume that string variables email and telephone already have values.

The algorithms that declare class objects can access the fields of the class only through the subprograms (called methods) of the class.

The fields in a class are private by default. That is, none of the fields, either data or method, of an object of a particular class can be accessed by any other object unless the field is marked public. If a class needs to make a method available to be called by an object of another class, the class must explicitly specify that the method is public. The Person class methods are marked public so that a using program can call them.

Inheritance

Inheritance is a property of object-oriented languages in which classes can inherit data and methods from other classes. This relationship is an “is-a” relationship. A superclass is a class being inherited from; a derived class is a class doing the inheriting. Classes form an inheritance hierarchy. In the hierarchy, objects become more specialized the lower in the hierarchy we go. Classes farther down in the hierarchy inherit all of the behaviors and data of their parent superclass.

In our latest example, we have been working with class Person. In an object-oriented language, we can define a class Student, which inherits all the properties of class Person and adds more data fields to hold the local address and telephone number. Objects of class Person have only one address and phone number, but objects of class Student have two: one inherited from class Person and one defined within class Student. We say that class Student is derived from class Person.

Here are the CRC card headings for Person and Student. Note that the Subclass and Superclass fields in the CRC cards have been filled in.

A screenshot for a class “Person” shows the following three fields: Class Name (Person), Superclass, and Subclasses (Student).
A screenshot for a class “Student” shows the following three fields: Class Name (Student), Superclass (Person), and Subclasses.

Let’s assume that we have defined classes Person and Student. The following algorithm instantiates classes Person and Student and manipulates them:

Inheritance fosters reuse by allowing an application to take an already-tested class and derive a class from it that inherits the properties the application needs. Other necessary properties and methods can then be added to the derived class.

Polymorphism

In the previous section, classes Person and Student both have methods named Print and Initialize. The method in class Person prints the address defined in its class, and the method in class Student prints the address defined in its class. Here we have two methods with the same name but different implementations. The ability of a programming language to handle this apparent ambiguity is called polymorphism. How does the language know which method is meant when Initialize or Print is invoked by the calling unit? Methods that are part of a class are applied to an instance of the class by the calling unit. The class of object to which the method is applied determines which versions of the Initialize or Print method are used.

For example, if we had jane as an instance of class Person and jack as an instance of class Student, jane.Print would invoke the method defined in class Person to print jane’s information. jack.Print would invoke the method defined in class Student to print jack’s information. The Student class could add a method PrintHomeAddress, which would then print the home address of a student.

The combination of inheritance and polymorphism allows the programmer to build useful hierarchies of classes that can be reused in different applications. Reuse does not apply only to object-oriented languages; however, the functionality of object-oriented languages makes writing general, reusable sections of code easier.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.8.82