198 Chapter 14 ■ The basics Answers to self-test questions 14.1 When some input from the user’s keyboard is required. It must be checked and, if necessary, new input solicited until the input is correct. 14.2 int[] table; boolean search(int wanted) { boolean found = false; int i = 0; endSearch: while (i < table.length) { if (table[i] == wanted) { found = true; break endSearch; } i++; } return found; } Without using break: int[] table; boolean search(int wanted) { boolean found = false; int i = 0; while (i < table.length and found == false) { if (table[i] == wanted) found = true; else i++; } return found; } 14.3 Yes and no. Clearly these operations are not something that should be allowed with integers and reals. But in Java the bit structure of these data types is precisely defined. Also the effects of these operations are precisely defined. So these par- ticular data types have an extended set of valid operations. BELL_C14.QXD 1/30/05 4:23 PM Page 198 Further reading 199 14.4 The benefits are program clarity, better modeling of the problem, compile- time checking and run-time checking. 14.5 This is a case of expressive power and convenience versus fast per- formance. 14.6 Arrays and records allow the programmer to create and use data struc- tures that match the problem to be solved in a convenient and natural fashion. This fosters fast development, reliability and maintainability. See the references at the end of Chapter 16. Further reading • BELL_C14.QXD 1/30/05 4:23 PM Page 199 Most current mainstream languages embody OOP. The three pillars of OOP are encap- sulation, inheritance and polymorphism. This chapter explains how the programming language can support these concepts. The language used for illustration is Java, and the case study is the cyberspace invaders game (Appendix A). We go on to explain how classes can be made more general using the concept of generics, sometimes termed templates. Next we discuss approaches to creating dynamic data structure – structures that expand and contract as necessary. In particular, we look at using pointers. Finally we explore the challenge of garbage collection – what happens to computer memory after it has been used as part of a dynamic data structure. Encapsulation means bringing together data and actions that are related. In OOP such a collection is called a class. It consists of some related variable declarations and some methods. A class is a template or blueprint for any number of objects that can be cre- ated from it. In many programming languages, including Java, this is accomplished using the key word new. Creating an object is also known as instantiating an object. We will use the example of the cyberspace invaders game, Figure 15.1, to illustrate encapsulation. The program displays a number of graphical objects at various times on 15.2 ● Encapsulation 15.1 ● Introduction This chapter: ■ explains how encapsulation, inheritance and polymorphism are provided in a programming language ■ explains the role of libraries in object-oriented programming ■ explains the idea of generics or templates ■ explains provision for dynamic data structures and garbage collection. CHAPTER 15 Object-oriented programming BELL_C15.QXD 1/30/05 4:23 PM Page 200 15.2 Encapsulation 201 the screen – an alien, a laser, a bomb and the user. We will represent each of these as an object. We will represent the alien as an object, but to create an object, we have to write a class (a blueprint for any number of aliens). In Java, we write the class as follows: class Alien { private int x, y; private int size; private ImageIcon alienImage; public Alien(int newX, int newY, int newSize) { x = newX; y = newY; size = newSize: alienImage = new ImageIcon("c:/alien.jpg"); } public void display(JPanel panel) { Graphics paper = panel.getGraphics(); alienImage.paintIcon(panel, paper, x, y); } Figure 15.1 Cyberspace invaders > BELL_C15.QXD 1/30/05 4:23 PM Page 201 202 Chapter 15 ■ Object-oriented programming public void moveLeft(int amount) { x = x – amount; } public void moveRight(int amount) { x = x + amount; } } As you can see, the class consists of a grouping of variable declarations, at the top, followed by methods. The public methods act as the outward appearance of the class, acting upon the private variables within it. The method Alien is termed a constructor method or simply a constructor. (In Java a constructor method has the same name as the class name.) It is called when an object is created from the class to initialize variables within the object. A class can have any number (including zero) constructors. We can now create an object named alien from the class Alien as follows: Alien alien = new Alien(100, 100, 10); And then we can use it: alien.moveLeft(100); alien.display(paper); Here we see the classic notation object.method which is so characteristic of OOP. SELF-TEST QUESTION 15.1 Add a method named moveDown to the class Alien. OOP supports the concept of information hiding, that is, users should be provided with sufficient information to use the data type but nothing more. Users of a class should be provided with a specification of the effect of each of the operations provid- ed and a description of how to use each operation. They should not be required to know the representation of the class nor be able to access the implementation other than indirectly through a method provided. The class Alien encapsulates and hides all the information about an alien and how it is to be used. The interior of the class is inaccessible from outside the class; this is enforced by the compiler. So no one can tamper – by mistake or malice – with the data that represents an alien. The only way that an alien object can be accessed is via the methods such as display and moveLeft that are provided. Thus access to an alien object is carefully controlled. This constitutes the best form of modularity – access is via method calls, rather than by direct access to data. Good style means that only in rare cases will a class permit direct access to data within itself. > BELL_C15.QXD 1/30/05 4:23 PM Page 202 15.2 Encapsulation 203 Often (though not in the Alien example shown above) there will need to be ad- ditional methods that the class needs in order to carry out its tasks. These are pri- vate methods that need not and therefore should not be accessible from outside the class. A class represents a real fusion of data and actions. A class extends the built-in data types provided by the language, so that the programmer can invent data suitable for the problem being solved. The programmer specifies how the data can be manipulated and thus creates truly abstract data. The advantages of encapsulation are: ■ to make useful classes generally available ■ to use a class without the need to know how it works ■ to have the flexibility to modify a class without affecting its users. Properties We have seen that it is very bad practice to make public any of the instance variables of a class. Some languages, for example, C# and Visual Basic, provide a mechanism that simulates accessing variables directly. This feature, called properties, enables users to have convenient but controlled access to the data associated with an object. In general there are two distinct kinds of access to data: 1. reading a value – called get access 2. writing the value – called set access. For example, suppose we want to allow a user of an alien object to refer to (get) the x coordinate of the alien and display its value in a text field. The value is held in the private variable named x at the top of the class. Using a property named xCoord, we can write: textField.setText(Integer.toString(alien.xCoord)); Suppose also that we want the user to be able to change (set) the value of the x coor- dinate. Using the property facility we can write: alien.xCoord = 56; The way to provide these facilities is to write a property. Here is the revised class that includes the property code: public class AlienWithProperties { private int x; private int y; private int size; private ImageIcon alienImage; > BELL_C15.QXD 1/30/05 4:23 PM Page 203 204 Chapter 15 ■ Object-oriented programming public Alien(int newX, int newY, int newSize) { x = newX; y = newY; size = newSize; alienImage = new ImageIcon("c:/alien.jpg"); } public void moveLeft(int amount) { x = x - amount; } public void moveRight(int amount) { x = x + amount; } public void display(JPanel panel) { Graphics paper = panel.getGraphics(); alienImage.paintIcon(panel, paper, x, y); } public int xCoord { get { return x; } set { x = value; } } } The header for a property looks similar to a method header, except that there are no brackets to specify parameters. The property consists of two complementary com- ponents – one has get as the heading and the other has set as the heading. The get part is like a function method – it returns the desired value. The set part is like a method – it assigns the value using the special keyword value as shown. Note that this code is in the style of Java, but it is not Java, since Java does not support a prop- erty mechanism. If we only need a way of viewing a property (but not changing its value), we write the property declaration like this: public int xCoord { get { return x; } } > > > BELL_C15.QXD 1/30/05 4:23 PM Page 204 15.2 Encapsulation 205 If, on the other hand we need to change a value, but do not need the facility to view it, we write: public int xCoord { set { x = value; } } When you see properties for the first time, you may be tempted to wonder why such a long-winded mechanism is needed. Surely it would be easier simply to declare the value x as public? Then the user of the object could simply refer to the value as alien.x. This is possible, but it is very bad practice – for the reasons discussed above to do with encapsulation. What the property feature gives is the appearance of direct access to data, with all the security of access via methods. > > SELF-TEST QUESTION 15.2 Write a property to allow a user only get access to the y coordinate of an alien. SELF-TEST QUESTION 15.3 In designing a class Account to represent a bank account, which of the following should be methods and which should be properties? creditAccount, debitAccount, currentBalance, calculateInterest, name Method or property? Some programming languages provide both methods and properties as mechanisms for accessing an object. So how do we choose which to use? The answer is to use methods when you want an object to carry out some action. (A method usually has a name that is a verb.) Use properties when you want to refer to some information associated with an object. (A property usually has a name that is a noun.) Examples of methods associated with an alien, discussed above, are: display, moveUp, moveDown, moveLeft, and moveRight. Examples of alien properties are: xCoord, yCoord, and size. Sometimes there is a choice over whether to make something a property or a method, and the choice is a matter of style. For example, to change the color of a com- ponent we could have a method changeColor; alternatively we could provide a prop- erty named color. Some people argue that the only proper access to objects is via method calls and that therefore properties are superfluous. BELL_C15.QXD 1/30/05 4:23 PM Page 205 206 Chapter 15 ■ Object-oriented programming Most modern languages are small – they provide a few simple facilities, such as control structures and the ability to write classes. The power of the language is provided by the libraries of ready-made classes that are supplied alongside the language. For example, most modern languages (including Java) provide a class ArrayList, which is like an array, but better. An array list is similar to an array in that it stores a collection of items, each of which is referred to using an integer subscript (index). But, in contrast to an array, items can be added or removed from anywhere within an array list. Also an array list grows and shrinks as necessary to accommodate the required data. An array list holds strings, integers, GUI components or any other type of data. To use an array list, you create an instance (an object) like this: ArrayList arrayList = new ArrayList(); Then you can add items to it, as shown in the example: arrayList.add(alien); which inserts the item at the end of the data. In common with other library classes, an array list comes with a useful set of meth- ods. Here are some of the methods for array lists. add(int index, Object item) inserts the specified item at the specified position add(Object item) appends the item to the end of the array list clear() removes all the items from the array list contains(Object item) returns true if the object is in the array list get(int index) returns the element at the specified position remove(int index) removes the element at the specified position set(int index, Object item) replaces the item at the specified position with the item size() returns the number of elements in the array list. So, facilities such as array lists are not part of the language but are provided as part of the library. Libraries typically provide a massive range of classes, so that the activity of programming becomes a search for useful classes. This is a view of programming in which the programmer writes very little code, instead making reuse of a vast repository of ready-made components. 15.3 ● Library classes BELL_C15.QXD 1/30/05 4:23 PM Page 206 15.4 Inheritance 207 Real-world systems depend on our ability to classify and categorize. Elephants, tigers, polar bears, horses and cows are all mammals; lead, silver and platinum are metals; sav- ings, current and term deposits are types of bank accounts, and so on. Through classi- fication, we are able to associate characteristics common to all members of a class. All mammals are vertebrates (have backbones), are warm-blooded and have hair on their bodies; all metals have atomic weights; and all bank accounts have balances. We often think of objects as specializations of other objects. Precious metals are specializations of metals, sports cars are specializations of cars, romance novels are spe- cializations of books, and so on. All precious metals are metals but not all metals are precious metals. Similarly, all sports cars are cars and all romance novels are books, but the reverse is not true. Similarly, quadrilaterals and triangles are polygons, and squares and rectangles are special kinds of quadrilaterals. Furthermore, a square is a special kind of rectangle. Extending this notion, we can view one class of objects as a subclass of another. We can also talk about one class being a superclass of another. What does it mean to say that one class is a subclass of another? Intuitively, we mean that the subclass has all the characteristics of the more general class but extends it in some way. Precious metals have all the characteristics of metals but, in addition, they can be distinguished from some metals on the basis of monetary value. Similarly, quadrilat- erals are specializations of polygons with four sides. Polygons can have any number of sides. Squares are specializations of quadrilaterals where all four sides have equal length, and adjacent sides are perpendicular to one another. Applying these arguments in reverse, we can describe the superclass of a class as being a generalization of the class. One of the best ways to describe something new to someone else is to describe it in terms of something that is similar, that is, by describing how it differs from something known. An example is that a zebra is a horse with stripes! This concise definition conveys a substantial amount of information to someone familiar with horses but not with zebras. We now extend the cyberspace invaders program so that we can create and display the other objects – the bomb, the laser and the user. We already have a class Alien that describes aliens. We now consider writing a class Bomb to describe bombs. But we soon realize that aliens and bombs have things in common, for example, their x, y coordi- nates and their size, so although we could write completely separate classes, we can 15.4 ● Inheritance SELF-TEST QUESTION 15.4 Write a class Stack that implements a first-in, last-out structure. Use an array list to hold items of type String. Provide public operations pop and push. push adds an item to the top of the stack. push removes an item from the top of the stack. The class could be used like this: Stack stack = new Stack(); stack.push("Mary"); BELL_C15.QXD 1/30/05 4:23 PM Page 207 . common to all members of a class. All mammals are vertebrates (have backbones), are warm-blooded and have hair on their bodies; all metals have atomic weights; and all bank accounts have balances. We. the array list. So, facilities such as array lists are not part of the language but are provided as part of the library. Libraries typically provide a massive range of classes, so that the activity of. the language. For example, most modern languages (including Java) provide a class ArrayList, which is like an array, but better. An array list is similar to an array in that it stores a collection