Chapter VIII Introduction to OOP Chapter VIII Topics 8.1 Introduction 8.2 OOP, a Gentle First Exposure 8.3 Encapsulation and Reliability 8.4 The Bank Class from Scratch 8.5 Method Summary Chapter VIII Making Object Methods and Encapsulation 311 8.1 Introduction In Chapter I you were introduced to a history of program languages. In that brief history of various languages you were told that C++ is a language with extensive Object Oriented Programming (OOP) features, but C++ can be written without using any type of OOP. Java on the other hand revolves around OOP. This means that you need to learn OOP to write correct Java programs and OOP needs to be a major part of a computer course. You are currently in a high school level computer science course, and topics are introduced in a slower and easier manner than the faster pace you will encounter in college. Nevertheless, slower or faster, the time has come to talk about OOP. You have actually already done a fair amount of OOP, but you were not really aware of this fact. OOP can easily overwhelm the new computer science student with its sizable vocabulary of obscure words along with an even more obscure set of definitions for these peculiar words. Words like encapsulation, inheritance, composition, instantiation and polymorphism are not intuitive household words for the average high school student. It is the aim of Exposure Java to give you a very thorough treatment of all the various OOP concepts. However, these concepts will be introduced with one small chunk at a time. OOP may be a formidable challenge to comprehend, but all challenges can be broken down into small manageable parts. This short chapter is but one, hopefully comfortable, stage along the road to master computer science with the Java programming language. You will also find that future chapters will repeat prior concepts frequently to reinforce what was learned earlier. If you continue to take the AP Computer Science course in high school or to take computer science in college, you will learn OOP extensively, and you will appreciate the introduction provided in this course. 8.2 OOP, a Gentle First Exposure Textbooks can be so helpful to the young, eager, but quite confused computer science student. You, the eager student, open a textbook excited to learn about Object Oriented Programming. Your textbook just oozes the wisdom of the ages, or at least the last few computer science decades. You just know this wisdom will be uploaded to your brain by osmosis or some other, equally mysterious process, which is known as studying in some circles. Actually, you feel pretty good 312 Exposure Java 2012, PreAPCS Edition 06-25-12 because you do understand most of the introductory material that you have been studying. You may have heard about OOP from some people, but you do not have a clue what the hype is all about. Maybe your textbook will clarify. In a pretty yellow box you now see the following definition: Object Oriented Programming (OOP) is a style of programming that incorporates the three features of encapsulation, polymorphism and class interaction. Well what could be clearer? Encapsulation has always been one of your hobbies. Polymorphism is a regular topic around the dinner table and every day in school you hope for some good class interaction. Why this kind of vocabulary? Simple! Professions generate vocabulary, which is known only to members of the profession to help identify its own members. The outsider people then need to pay big bucks to acquire the services of the inside professionals. Doctors, lawyers, accountants, educators and yes computer scientists all have a set of vocabulary to add prestige and economic benefits to the profession. Think we are kidding? Consider the following invoice by a network technician who fixes a computer network problem. Repaired layer-1 radical disruption to the layer-2 NIC, which resulted in a failure of any frame to identify the appropriate MAC address of the destination host, while simultaneously disallowing the NIC to perform its usual role of CSMA/CD of the Ethernet protocol. Translation: the network cable was not plugged in. Now how can you charge $300.00 by stating on an invoice that you plugged in a cable? OK, back to OOP, and the whole point of this tangent is to explain that unpleasant vocabulary needs to be accepted. It comes with any profession. Do not think that a concept is complex because the vocabulary sounds intimidating. Professional vocabulary is meant to be intimidating. Once you work with the language it is no longer a big deal. So, now that you have accepted that encapsulation, polymorphism and class interaction are a way of computer science life, let us see what this really means. Forget computer science right now and think objects. What comes to mind? It probably depends on your age, culture, gender and upbringing but we bet that every object you think about has nouns and verbs. What does that mean? Well let us look at cars. Cars have many objects. They have seats, doors, lights, seat belts, wheels, radios, engines, transmissions and many other objects that make up the entire car. Now each of these objects has both nouns and verbs. Sounds weird? Consider a radio. A radio has buttons and/or knobs, which can be pushed Chapter VIII Making Object Methods and Encapsulation 313 or turned. A radio also has a display screen. A knob, a button and a display are nouns, and each one of these nouns does something. A knob turns to the desired frequency. A button turns the power on and off. The display shows the current frequency or the CD that is played. The actions performed by the nouns are the verbs. Everywhere you look, you are surrounded by many objects. Object Oriented Programming simulates real life by using a program style that treats a program as a group of objects. Now in OOP we do not use the term nouns and verbs. You may hear many different terms being used but currently the more popular terms are attributes and methods. Attributes store program information, which is like a noun. Methods perform some actions on the information, which is like a verb. For example, imagine that you have a student object. In this object the attributes are all the student records of information. The object also contains the ability to add, search, delete, alter, sort and display these student records. Adding, searching, deleting, altering, sorting and displaying the records are all methods. You have already encountered many methods in Java. Both print and println are methods you learned early in this course. Methods are program modules that perform some task. In the case of print the task is to display information in a text window. You have also worked with methods of the Math and the Expo classes. The significance of Object Oriented Programming is that attributes and methods are packaged in the same container, the same object or the same capsule. This accounts for the name encapsulation. The intention of encapsulation is to make a program more reliable. The earlier, non-OOP, languages would keep the attributes, the information stored by a program, separate from the functions, procedures, actions or methods that process the information. This separation would frequently result in unintended and very undesirable program errors. Do not even try to think about how all this is achieved. The details come later. This is meant to be an introduction of general concepts. Where is the reliability in all this encapsulation business? Imagine that you want to have a reliable lumberyard delivery system. Your job is to drop off large quantities of lumber at a customer's site. Now this lumber is very heavy. At the lumberyard you have forklifts to load the lumber. How about unloading the lumber at the customer location? Perhaps the customer is at a construction site with a forklift. Perhaps the forklift is in use, is too large or is too small or maybe the customer does not have a forklift at the job site at all. If we keep the lumber (attribute) separate from the forklift (method) that handles the lumber we may have serious problems delivering the lumber efficiently, safely and reliably. The solution is to attach a forklift to the back-end of the delivery truck. We now have a delivery object. The object stores the lumber, moves the lumber and unloads the lumber. Everything required to manage the lumber is contained in the same object. The containment or encapsulation of materials or 314 Exposure Java 2012, PreAPCS Edition 06-25-12 information and the processes that access the materials is the corner stone of OOP. Encapsulation increases reliability tremendously. In this chapter no attempt will be made to explain polymorphism and class interaction. Both polymorphism and class interaction are important programming tools in the goal to design reliable programs. How this is done will be explained in future chapters and courses. Right now the focus will be on encapsulation. Encapsulation Java encapsulates data and action modules that access the data in one container, called an object. Object members that perform some task are called methods. Object members that store data are called attributes. This is not your first trip on the methods merry-go-around. You have already learned about using class methods and using object methods in earlier chapters. You have also learned how to write class methods. This chapter will round out the difference between writing a class method and an object method for you. There will be many program examples provided. Most of the examples are sequential and need to be examined in their proper order. 8.3 Encapsulation and Reliability You have seen classes and methods since Chapter II. You learned about Java program organization in Chapter IV. Java programs have containers. Containers that perform some singular process are called methods. Methods are tools. A collection of common tools are placed in a toolkit container called a class. The process of placing data attributes and the action methods that access the data in the same container is called encapsulation. Why is that reliable? Chapter VIII Making Object Methods and Encapsulation 315 To answer the Object Oriented Programming connection with reliability we need to take a history lesson and see what prior program design approaches were used. Programming did not start with classes and objects. We can identify four distinct stages of program design. Let us take a look at each stage. The four stages explained here are somewhat of an over-simplification of the evolution of programming style, but this will do nicely to give you a brief over- view of where computer science has been and where we are today. The Four Stages of Program Design Cryptic Programming Stage Unstructured, Spaghetti-Programming Stage Structured Programming Stage Object Oriented Programming Stage Cryptic Programming Stage In the very early days of programming, computers were incredibly expensive and programmers were very cheap. Computers cost more than one million dollars and a programmer could be hired for $5,000 a year. Programs were written without any thought about design. As a matter of fact, many programs were written intentionally in a very cryptic style that only the creator of the program could understand. This style of programming assisted a programmer with job security and it also stroked egos as only the programmer, the exulted mastermind, could fix or alter the program at the awe of other lesser-blessed mortals. This style of programming did not last long. Computers became cheaper and programmers became more expensive. Programs required frequent debugging and updating, and the cryptic style usually meant starting a program from scratch if the creator left the company. Companies could not afford this wasteful approach. 316 Exposure Java 2012, PreAPCS Edition 06-25-12 Unstructured, Spaghetti-Programming Stage The next stage made attempts at being less cryptic. An effort was started to use better, meaningful identifiers, comment program code to assist in updating and provide external documentation for future programmers. But a major problem lurked at this stage in the form of the goto statement. Programs then and now rarely worked immediately. Program errors were found and needed to be fixed and sometimes bugs showed up continuously as the program aged. A program requires some type of control sequence, which guides the flow of program execution and in large programs this program flow would frequently be faulty. A quick fix was to use a goto statement to put the program back on track. Unfortunately, as programs grew so did the number of goto statements and large programs were mazes with many program statements linked to many other parts in the programs. People unfamiliar with the design of such programs would often use a pencil and draw the program flow on a printout of the source code. Such drawings resulted in a spaghetti appearance of criss-crossing lines and the term spaghetti programming was born. Structured Programming Stage Programs in the past and today have one common goal that allows no compromise. This goal is reliability. A program must work correctly. It is nice if a program executes rapidly, but no amount of speed can excuse a program that is unreliable. Spaghetti programming is a major drawback to reliability. The many goto statements are basically a quick band-aid for a flawed program and once there are so many band-aids, the whole structure becomes weak, is very unreliable, and crashes easily. It is no longer possible to have any type of overview of the program execution. A new style of programming was developed called structured programming. It is not easy to explain exactly what that kind of programming involves, but you can appreciate this. Goto statements received the boot and were no longer used. Program flow was strictly controlled with one entrance and one exit and program statements with a common purpose were grouped together in special modules. The philosophy was called one-task-one-module. Structured programming greatly improved the creation, debugging and updating of programs. Reliability was increased along the way. Chapter VIII Making Object Methods and Encapsulation 317 Object Oriented Programming Stage Structured programming did just fine in the earlier world of text-style output. Programs were simpler and shorter than the later windows-graphics-style programs. The incredible complexity of current programs brought on a new challenge in reliability. Program users expect programs to look attractive, provide on-line help, be user-friendly, and yes they still need to be reliable. The length of programs grew incredibly. Many programs in the late Eighties and early nineties could fit on three to five floppy diskettes. That changed dramatically as today's software is lucky to fit on one CD. Somehow with this new magnitude of programming, structured programming could not keep up. A level of program complexity had arrived that required a new approach. This chapter will give a brief introduction to Object Oriented Programming. Please accept right now that OOP has many features specifically designed to make a program easier to develop, simpler to debug and faster to test with confidence. Program development with OOP has brought a new level of program reliability. This also explains why universities have embraced Java as an introductory programming language. C++ used to be a popular program language in computer science classes. C++ has all the powerful OOP features and C++ was and still is an extremely important language in the computer science community and software industry. The key problem with using C++ at the introductory level is that C++ can be used without OOP at all. In a world where students need to be thinking about OOP from the beginning, C++ can be problematic. Java, on the other hand, is pure OOP. You are not asked if you like OOP or want to do OOP. Oh no, if you program in Java you will be up to your nostrils in OOP. We mentioned the lumber delivery object earlier as an example of insuring reliability by including a forklift with the delivery truck. Now consider an airport. Does an airport use OOP principles like encapsulation? Think about this. You are flying from Dallas to Seattle. You walk up to the counter and check your luggage. Where does your suitcase go? It is placed on a conveyer belt behind the check-in counter. So everything is great. Now the person behind you flies to Miami. Where does his bag go? You know it; the bag is placed on the exact same conveyer belt. As a matter of fact if your check-in counter is used for flights to 50 different destinations then all the luggage for all 50 destinations start on the same conveyer belt. Now imagine an oopified airport. At the terminal there is a large door with the sign Seattle Passengers. You enter the door and you notice that there is a single hallway. It is not possible to go in multiple directions. You notice other passengers in other hallways through the glass walsl. Those passengers cannot enter you hallway and you cannot enter their hallway. At the check-in counter your bags are placed on a conveyer belt, which only goes to one gate. It is the 318 Exposure Java 2012, PreAPCS Edition 06-25-12 gate for the Seattle flights. You continue through the security process and finally end up at a single gate. The plane at the gate goes to Seattle. You notice that the single luggage conveyer belt also ends at the gate. Everything in this airport is dedicated for a single destination. Your destination, Seattle, is encapsulated into a single container or hallway. All the procedures in this container are reserved for the Seattle passengers. In such an airport, the reliability is increased tremendously and such an airport actually exists, but it is not for the general public. There are airports for private jets that behave in this manner. Make a lot of money, become a multi-millionaire and then you can experience that degree of reliability. 8.4 The Bank Class from Scratch In Chapter VII you first started to create your own classes and methods. In that chapter you strictly created the type of classes that only store class methods. There was a reason for that approach. Creating class methods is simpler than creating object methods. Class methods process parameter values; they do not process the data attributes values. You did see in the Math class that it contained attributes PI and E, but those attributes were not processed. PI and E exist as constant mathematical values. They do not store values that are unique to some object. You have used object methods and you learned that an object must be created with the new operator. After the object was constructed the object methods had the ability to store, alter and display attribute values. You will now see how such a class is created. In ten small steps the Bank class will be created. Program Java0801.java, in figure 8.1, is about as simple as it can get. You see a Bank class ... or more appropriately some empty container with a heading that states class Bank. At this stage the Bank class does nothing, but it shows a very important principle. Before you can put tools in a toolkit, you need a toolkit. The first program example does compile. You need to start with a heading and a set of braces that will contain the class member, both attributes and methods. Figure 8.1 // Java0801.java // Stage #1 of the <Bank> class // The only thing that is done in this stage is the creation of a container. // It is the "container" or "block" or officially the "class" which will be the // toolkit for all the different tool necessary to handle bank transactions. // This <Bank> class is minimal program code. It does nothing, but it will compile. // The <Java0801> class contains the <main> method used to test our user-created class. Chapter VIII Making Object Methods and Encapsulation 319 public class Java0801 { public static void main(String args[]) { System.out.println("\nJAVA0801.JAVA\n"); } } class Bank { } // // The class heading of the <Bank> class The opening brace of the <Bank> container // All elements of the <Bank> must be placed between the braces // The closing brace of the <Bank> container Figure 8.1 Continued Is it possible to construct an object when the class is totally empty? Program Java0802.java, in figure 8.2, says yes! There still is no output, but Java seems to have little difficulty creating an object with absolutely zero information. Perhaps Java thinks that if you give me nothing, you will get nothing in return. The output is the same as the previous program. Figure 8.2 // Java0802.java // Stage #2 of the <Bank> class // In the second stage the main method creates a <Bank> object, called <tom>. // Java does not complain. A pretty much useless <tom> object is created. public class Java0802 { public static void main(String args[]) { System.out.println("\nJAVA0802.JAVA\n"); Bank tom = new Bank(); } } class Bank { } 320 Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.2 Continued Program Java0803.java, in figure 8.3, takes the simple approach that you use the object name, followed by a dot and then followed by some object member and everything is just great. That may seem logical and it actually works in this program. Guys this is really, really bad programming. Since this is a Bank class consider the following real-life situation. You have $10,000 in the bank and you need $4000. No problem. You walk in the bank, open the vault and help yourself to $4000. That may seem correct, because you do have the money, but such an approach has all type of reliability issues. You can be the most honest customer in the world, but you have counting issues. It is possible that you take too much or too little money. Either way is bad. You can also be dishonest and take too much money. The only way a bank lets you have money is with the aid of a bank teller. This gives reliability and that is what we need to do with our class. Figure 8.3 // Java0803.java // Stage #3 of the <Bank> class // This program may seem logical. Values are assigned to program variables. // The data variables are inside the <tom> class container. // The object.identifier syntax seems as it was shown in previous chapters. // //////////// THIS IS BAD OLD-STYLE PROGRAMMING ////////// public class Java0803 { public static void main(String args[]) { System.out.println("\nJAVA0803.JAVA\n"); Bank tom = new Bank(); tom.checkingBal = 1000.00; tom.savingsBal = 3000.00; System.out.println("Checking Balance: " + tom.checkingBal); System.out.println("Savings Balance: " + tom.savingsBal); System.out.println("\n\n"); } } class Bank { double checkingBal; double savingsBal; } // data attribute to store the object's checking balance // data attribute to store the object's savings balance Chapter VIII Making Object Methods and Encapsulation 321 Figure 8.3 Continued A bank uses a simple protection device. One of its important attributes, money, is locked away. The money sits in a vault and the vault is only opened by designated bank employees. A small amount of cash is in a drawer with each bank teller. The drawer is always locked when the teller moves away. So we need to lock up our money or data attributes so that outsiders - meaning program statements from outside the Bank class - cannot have access to the data. This is accomplished in Java0804.java, in figure 8.4, by using the reserved word private. When the two data attribute are declared as private, it means that only local members of the Bank class have access. The program does not compile, because statements from outside the Bank class attempt access. Figure 8.4 // Java0804.java // Stage #4 of the <Bank> class // This protects the checking and savings balances from outside alteration // by making them private attributes. public class Java0804 { public static void main(String args[]) { System.out.println("\nJAVA0804.JAVA\n"); Bank tom = new Bank(); tom.checkingBal = 1000.00; tom.savingsBal = 3000.00; System.out.println("Checking Balance: " + tom.checkingBal); System.out.println("Savings Balance: " + tom.savingsBal); System.out.println("\n\n"); } } class Bank { private double checkingBal; private double savingsBal; } 322 // data attribute to store the object's checking balance // data attribute to store the object's savings balance Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.4 Continued Private and Public Members Members in a class need to be declared as private or public. Private members cannot be accessed by any program statements outside the class. Public members of a class can be accessed by program segments outside the class. Data attributes of a class usually need to be declared private. Methods of a class usually need to be declared public. Program Java0805.java, in figure 8.5, adds an excellent reliability feature. A special method is placed inside the container, which initializes the values of the data attributes. In this case the balance of both checking and savings is set to zero. The name of the method that performs this process is Bank, which is the same name as the class itself. This is intentional. A class with object methods has a special method, called a constructor, which has the job to get a new object ready for work. It may appear that Bank is used twice in one statement. That actually is not true. Consider the following statement: Bank tom = new Bank(); Chapter VIII Making Object Methods and Encapsulation 323 The first Bank is the class name. Object tom is one variable, or more commonly called, instance of the Bank class. The second Bank() has parentheses, which right away indicates that this is a method call. So the second Bank is a call to the constructor method Bank() of the Bank class. This process is called the construction of the tom object. It is also called the instantiation of the tom object. The name indicates that this the precise moment when memory space is allocated for the new object and the constructor method is called to initialize the data attribute values of the new object. Even though it is very common to initialize attribute values in the constructor method, it is not the only process that occurs in the constructor. Any type of action that is practical to occur to get the new object ready for work is considered appropriate. For instance, you may have a CardDeck class, which is used for some game program like Blackjack, Poker or other card games. The constructor for such a class may not only initialize data attributes, but also call a method that shuffles the deck during instantiation of a new object. The reliability of the constructor is based on the fact that the constructor method is called automatically. Figure 8.5 // Java0805.java // Stage #5 of the <Bank> class // This stage adds a "constructor" method, which initializes the both balances to zero. // The constructor is automatically called when the new object (line 12) is constructed. // There is no output, because data is assigned, but not displayed. public class Java0805 { public static void main(String args[]) { System.out.println("\nJAVA0805.JAVA\n"); Bank tom = new Bank(); } } class Bank { // The attributes (data variables) are usually listed first inside the class container. private double checkingBal; private double savingsBal; // The methods (modules that process attributes) usually start with the constructor. // The constructor has the same name as the class and initializes the data variables. public Bank() { checkingBal = 0.0; savingsBal = 0.0; } } 324 Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.5 Continued Instantiation and Construction A class is a template that can form many objects. An object is a single variable instance of a class. Objects are sometimes called instances. An object is created with the new operator. The creation of a new object is called: instantiation of an object construction of an object The special method that is called during the instantiation of a new object is the constructor. The previous program did have a constrcutor, but there was no output. Values were assigned to the attributes, but there were no methods that accessed the attributes for output. Program Java0806.java, in figure 8.6, corrects that problem. The Bank class now has two additional methods, which are called get methods. Such methods get values. They are read-only methods, because data values are accessed, but not altered. Figure 8.6 // Java0806.java // Stage #6 of the <Bank> class // Two methods are added to access the attribute values for public use. // It is now possible to see the balances of the bank account. public class Java0806 { public static void main(String args[]) { System.out.println("\nJAVA0806.JAVA\n"); Bank tom = new Bank(); Chapter VIII Making Object Methods and Encapsulation 325 System.out.println("Checking Balance: System.out.println("Savings Balance: " + tom.getChecking()); " + tom.getSavings()); System.out.println("\n\n"); } } class Bank { private double checkingBal; private double savingsBal; // The methods (modules that process attributes) usually start with the constructor. // The constructor has the same name as the class and initializes the data variables. public Bank() { checkingBal = 0.0; savingsBal = 0.0; } // The next two methods are "read-only" methods that return private data values. // Such methods are traditionally called "get methods" and "get" is often in the name. public double getChecking() { return checkingBal; } public double getSavings() { return savingsBal; } } Figure 8.6 Continued It is nice that the constructor initializes attribute values, but if the constructor always makes the account balances zero, then the program is not very realistic. Most of the time customers open an account with a starting balance. It is possible to create a second or even third constructor which has the same method name, but now includes a set of parameters, which gives the method a different heading or signature. Program Java0807.java, in figure 8.7, adds a second constructor, which allows the bank balances to get a specified initial value. Multiple methods with the same identifier are called overloaded methods. 326 Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.7 // Java0807.java // Stage #7 of the <Bank> class // This stage demonstrates how to create an "overloaded" method. // The second constructor has the same identifier as the first constructor. // However, the second constructor has a different heading signature. // Java knows which method to use by checking the parameters. // A second constructor allows user-input for the constructor. // This program also shows that is it possible to have two bank accounts. // This is only possible with a class that has object methods. public class Java0807 { public static void main(String args[]) { System.out.println("\nJAVA0807.JAVA\n"); Bank tom = new Bank(); Bank sue = new Bank(2000.0,2000.0); System.out.println("Tom's Checking Balance: " + tom.getChecking()); System.out.println("Tom's Savings Balance: " + tom.getSavings()); System.out.println(); System.out.println("Sue's Checking Balance: " + sue.getChecking()); System.out.println("Sue's Savings Balance: " + sue.getSavings()); System.out.println("\n\n"); } } class Bank { /////////// ATTRIBUTES ////////// private double checkingBal; private double savingsBal; ////////// CONSTRUCTOR METHODS ////////// public Bank() { checkingBal = 0.0; savingsBal = 0.0; } public Bank(double cBal, double sBal) { checkingBal = cBal; savingsBal = sBal; } ////////// GET "READ-ONLY" METHODS ////////// public double getChecking() { return checkingBal; } public double getSavings() { return savingsBal; } } Chapter VIII Making Object Methods and Encapsulation 327 Figure 8.7 continued Constructor Notes Constructors are methods, which are called during the instantiation of an object with the new operator. The primary purpose of a constructor is to initialize all the attributes of newly created object. Constructors have the same identifier as the class. Constructors are neither void methods nor return methods. Constructors can be overloaded methods. The method identifier can be the same, but the method signature (which is the parameter list) must be different. A constructor with no parameters is called a default constructor. The Bank class is steadily improving. Stage #8, in figure 8.8, adds two methods that can alter the account balances by making deposits. Keep in mind that the whole point of creating computer programs is to simulate what happens in real life. The methods in a class are meant to perform those same actions that need to be performed in a real situation. 328 Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.8 // Java0808.java // Stage #8 of the <Bank> class // Two methods are added that can read/write the attributes. // These are methods that make deposits to the checking and savings accounts. public class Java0808 { public static void main(String args[]) { System.out.println("\nJAVA0808.JAVA\n"); Bank tom = new Bank(1000.0,3000.0); Bank sue = new Bank(2000.0,2000.0); tom.checkingDeposit(1000.0); sue.savingsDeposit(2500.0); System.out.println("Tom's Checking Balance: System.out.println("Tom's Savings Balance: System.out.println(); System.out.println("Sue's Checking Balance: System.out.println("Sue's Savings Balance: System.out.println("\n\n"); } } " + tom.getChecking()); " + tom.getSavings()); " + sue.getChecking()); " + sue.getSavings()); class Bank { /////////// ATTRIBUTES ////////// private double checkingBal; private double savingsBal; ////////// CONSTRUCTOR METHODS ////////// public Bank() { checkingBal = 0.0; savingsBal = 0.0; } public Bank(double cBal, double sBal) { checkingBal = cBal; savingsBal = sBal; } ////////// GET "READ-ONLY" METHODS ////////// public double getChecking() { return checkingBal; } public double getSavings() { return savingsBal; } ////////// SET or MUTATOR "READ/WRITE" METHODS ////////// public void checkingDeposit(double amount) { checkingBal += amount; } public void savingsDeposit(double amount) { savingsBal += amount; } } Chapter VIII Making Object Methods and Encapsulation 329 Figure 8.8 continued Program Java0809.java, in figure 8.9, continues adding methods. In this case two additional methods are added to withdraw money from the checking or savings account. Figure 8.9 // Java0809.java // Stage #9 of the <Bank> class // Two more methods are added that can read/write the attributes. // These are methods that make withdrawals from the checking and savings accounts. // Note that the withdrawal methods have no protection against taking out more money than you have. public class Java0809 { public static void main(String args[]) { System.out.println("\nJAVA0809.JAVA\n"); Bank tom = new Bank(1000.0,3000.0); Bank sue = new Bank(2000.0,2000.0); tom.savingsWithdrawal(2500.0); sue.checkingWithdrawal(2500.0); System.out.println("Tom's Checking Balance: System.out.println("Tom's Savings Balance: System.out.println(); System.out.println("Sue's Checking Balance: System.out.println("Sue's Savings Balance: System.out.println("\n\n"); " + tom.getChecking()); " + tom.getSavings()); " + sue.getChecking()); " + sue.getSavings()); } } class Bank { /////////// ATTRIBUTES ////////// private double checkingBal; private double savingsBal; 330 Exposure Java 2012, PreAPCS Edition 06-25-12 ////////// CONSTRUCTOR METHODS ////////// public Bank() { checkingBal = 0.0; savingsBal = 0.0; } public Bank(double cBal, double sBal) { checkingBal = cBal; savingsBal = sBal; } ////////// GET "READ-ONLY" METHODS ////////// public double getChecking() { return checkingBal; } public double getSavings() { return savingsBal; } ////////// SET or MUTATOR "READ/WRITE" METHODS ////////// public void checkingDeposit(double amount) { checkingBal += amount; } public void savingsDeposit(double amount) { savingsBal += amount; } public void checkingWithdrawal(double amount) { checkingBal -= amount; } public void savingsWithdrawal(double amount) { savingsBal -= amount; } } Figure 8.9 Continued Chapter VIII Making Object Methods and Encapsulation 331 If you look closely at this output you should notice that something is wrong. Sue is withdrawing $2500 from her checking account, when she only has $2000. This type of thing should be prevented. It is the very reason we create special methods to access the data. These methods can control the access and in this case, prevent what bankers call “overdraft”. Program Java0810.java in figure 8.10 improves the 2 withdrawal methods so that overdraft is prevented. Figure 8.10 // Java0810.java // Stage #10 of the <Bank> class // The withdrawal methods now protect against overdraft. // Some extra printlns are added for clarification. public class Java0810 { public static void main(String args[]) { System.out.println("\nJAVA0810.JAVA\n"); Bank tom = new Bank(1000.0,3000.0); Bank sue = new Bank(2000.0,2000.0); System.out.println("Tom asks to withdraw $2500 from savings."); tom.savingsWithdrawal(2500.0); System.out.println("Sue asks to withdraw $2500 from checking."); sue.checkingWithdrawal(2500.0); System.out.println("Tom's Checking Balance: System.out.println("Tom's Savings Balance: System.out.println(); System.out.println("Sue's Checking Balance: System.out.println("Sue's Savings Balance: System.out.println("\n\n"); " + tom.getChecking()); " + tom.getSavings()); " + sue.getChecking()); " + sue.getSavings()); } } class Bank { /////////// ATTRIBUTES ////////// private double checkingBal; private double savingsBal; ////////// CONSTRUCTOR METHODS ////////// public Bank() { checkingBal = 0.0; savingsBal = 0.0; } public Bank(double cBal, double sBal) { checkingBal = cBal; savingsBal = sBal; } 332 Exposure Java 2012, PreAPCS Edition 06-25-12 ////////// GET "READ-ONLY" METHODS ////////// public double getChecking() { return checkingBal; } public double getSavings() { return savingsBal; } ////////// SET or MUTATOR "READ/WRITE" METHODS ////////// public void checkingDeposit(double amount) { checkingBal += amount; } public void savingsDeposit(double amount) { savingsBal += amount; } public void checkingWithdrawal(double amount) { if (amount > checkingBal) System.out.println("Insufficient Funds! Transaction Refused!\n"); else checkingBal -= amount; } public void savingsWithdrawal(double amount) { if (amount > savingsBal) System.out.println("Insufficient Funds! Transaction Refused!\n"); else savingsBal -= amount; } } Figure 8.10 Continued Sue’s request to withdraw $2500 from checking is refused because she only has $2000. Chapter VIII Making Object Methods and Encapsulation 333 For convenience sake you have seen two classes in the same file. Each file had a class with the same name as the file, like Java0810.java. This was the class that contained the main method and tested the Bank class. It is much better program design to place each class in its own file. When you do this, make sure to declare the class as public. Program Java0811.java, in figure 8.11, does not add any new Bank class features. You do only see the Java0811 class in the file. The Bank class is now in a separate file, called Bank.java and shown in figure 8.12. Figure 8.11 // Java0811.java // Stage #11 of the <Bank> class // The final stage of the <Bank> removes the class from the <Java0810.java> file // and creates a separate file, called Bank.java. public class Java0811 { public static void main(String args[]) { System.out.println("\nJAVA0811.JAVA\n"); Bank tom = new Bank(1000.0,3000.0); Bank sue = new Bank(2000.0,2000.0); tom.checkingWithdrawal(500.0); sue.savingsWithdrawal(800.0); System.out.println("Tom's Checking Balance: " + tom.getChecking()); System.out.println("Tom's Savings Balance: " + tom.getSavings()); System.out.println(); System.out.println("Sue's Checking Balance: " + sue.getChecking()); System.out.println("Sue's Savings Balance: " + sue.getSavings()); System.out.println("\n\n"); } } 334 Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.12 // Bank.java // Stage #11 of the <Bank> class // The <Bank> is now placed in its own file, which is better program design. // You must now declare the class as "public". public class Bank { /////////// ATTRIBUTES ////////// private double checkingBal; private double savingsBal; ////////// CONSTRUCTOR METHODS ////////// public Bank() { checkingBal = 0.0; savingsBal = 0.0; } public Bank(double cBal, double sBal) { checkingBal = cBal; savingsBal = sBal; } ////////// GET "READ-ONLY" METHODS ////////// public double getChecking() { return checkingBal; } public double getSavings() { return savingsBal; } ////////// SET or MUTATOR "READ/WRITE" METHODS ////////// public void checkingDeposit(double amount) { checkingBal += amount; } public void savingsDeposit(double amount) { savingsBal += amount; } public void checkingWithdrawal(double amount) { if (amount > checkingBal) System.out.println("Insufficient Funds! Transaction Refused!\n"); else checkingBal -= amount; } public void savingsWithdrawal(double amount) { if (amount > savingsBal) System.out.println("Insufficient Funds! Transaction Refused!\n"); else savingsBal -= amount; } } Think way back to Chapter II. In that chapter you were told the name of the file must always match the name of the class. Now you see the reason why. If they did not match one file would not be able to find a class stored in another file. Chapter VIII Making Object Methods and Encapsulation 335 8.5 Method Summary The primary focus of this chapter was on creating classes with object methods as opposed to creating class methods introduced in the last chapter. By now you have already seen an amazing number of different methods. In an effort to clarify all these methods, this chapter will conclude with a review of each type of method. Each method will be briefly explained and then an example of such a method is shown to review the precise Java syntax that is required. Class or Static Methods Class methods are sometimes called static methods because they have the keyword static in their heading. A class method is called with the class identifier, not with an object of the class. This is practical when there is no need to make multiple objects of a class. A good example is Java’s Math class. Everybody can use the methods of the Math class and there is no need to make multiple objects. The value of PI will be same with everybody using this class. Use the reserved word static at the start of a method heading to indicate that the method is a class method. In figure 8.13 notice how each method in the Piggy class is called by using the class identifier Piggy. Figure 8.13 public class Demo { public static void main(String args[]) { Piggy.initData(); Piggy.showData(); Piggy.addData(1200); Piggy.showData(); } } class Piggy { public static double savings; public static void initData() public static void addData(double s) public static void showData() } 336 { savings = 0; } { savings += s; } { System.out.println("Savings: " + savings); } Exposure Java 2012, PreAPCS Edition 06-25-12 Object or Non-Static Methods Object methods are sometimes called non-static methods because they do NOT have the keyword static in their heading. Object methods are meant for those situations where multiple objects of a class must be constructed. The essence of the method does not change. What really changes is the fact that now an object must be constructed first with the new operator, and then the method can be called. In contrast to the class methods, object methods are called by using the object identifier. In the example below, the same Piggy class is used, with the same methods. Now the methods do not use the static keyword and figure 8.14 shows that any object must be called with an object identifier, like tom. Figure 8.14 public class Demo { public static void main(String args[]) { Piggy tom = new Piggy(); tom.initData(); tom.showData(); tom.addData(1200); tom.showData(); } } class Piggy { private double savings; public void initData() { savings = 0; } public void addData(double s) { savings += s; } public void showData() { System.out.println("Savings: " + savings); } } Chapter VIII Making Object Methods and Encapsulation 337 Public Methods A public method can be accessed by members of the same class, and more importantly public methods can be accessed by any client of the class. Essentially, public methods can be accessed anywhere. The majority of methods are public. Method getCards, in figure 8.15 is public. Figure 8.15 public int getCards() { return cardsLeft; } Private or Helper Methods Occasionally, a method is created in a class that is never called outside of the class. In such a case, the method should be declared private. These private methods are sometimes called helper methods because they help and support the other methods of the class. For example, the Expo class has methods drawStar and fillStar which are both public method. There are some complicated mathematical processes that need to be computed to make the star methods work. These processes are in a separate method which is called by both drawStar and fillStar. There is no point in telling you the name of this method. It is private and cannot be called outside of the Expo class. If you are really curious, load Expo.java and see for yourself. Void Methods There are many ways to classify methods. Methods are not just public only, or private only, or static only, or anything else only. You, personally, have many classifications at the same time. You can be a Freshman, Sophomore, Junior or Senior. At the same time you can be Male or Female. You can also belong to a religious group and you can be Catholic, Muslim, Jewish, Protestant, or no religion at all. Classification also can be based on school organizations. You can be a band member, cheerleader, football player, gymnast, soccer player, academic decathlon member, etc. The point is do not be surprised if you see that a method shows up in many different classifications. The method in figure 8.16 is a public method, but for the purpose of this classification we are interested in the fact that it is a void method. Void methods do not return a value and use the reserved word void to indicate that no value will be returned. 338 Exposure Java 2012, PreAPCS Edition 06-25-12 Figure 8.16 public void ShowData() { System.out.println("Name: " + name); System.out.println("Savings: " + savings); } Return Methods Return methods are methods that return a value. Two features are necessary for a return method, and look for them in figure 8.17. First, you will see that the method heading indicates a data type, which is the type that the method returns, unlike void method whose return type is void. Second, you see a return statement at the end of the method body. Figure 8.17 public double getSavings() { return savings; } Default Constructor Methods A constructor is a special method that is automatically called during the instantiation of a new object. If no visible constructor is provided, Java will provide its own constructor, called a default constructor. Additionally, we also call a no-parameter constructor a default constructor, like the example shown in figure 8.18. Constructors are always public and they are special methods that are neither void nor return methods. Figure 8.18 public CardDeck() { System.out.println("Constructing a default CardDeck object"); numDecks = 1; numPlayers = 1; cardsLeft = 52; shuffleCards(); } Chapter VIII Making Object Methods and Encapsulation 339 Overloaded Constructor Methods An overloaded constructor is a second, third or more, constructor that allows a new object to be instantiated according to some specifications that are passed by parameters. Figure 8.19 shows an overloaded CardDeck constructor, which enters numDecks and numPlayers information. Figure 8.19 public CardDeck(int d, int p) { System.out.println("Constructing a CardDeck object with parameters"); numDecks = d; numPlayers = p; cardsLeft = d * 52; shuffleCards(); } Accessing or Get Methods Methods that only access object data without altering the data are called accessing methods or frequently get methods. Most accessing methods are return methods, which return object private data information. The example in figure 8.20 returns the value of numDecks. Figure 8.20 public int getDecks() { return numDecks; } 340 Exposure Java 2012, PreAPCS Edition 06-25-12 Altering or Modifier or Mutator or Set Methods Altering methods are sometimes also called modifier methods or mutator methods or set methods. These are methods that not only access the private data of an object; they also alter the value of the data. The example in figure 8.21 accesses the savings attribute and adds the value of s to it. Figure 8.21 public void savingsDeposit(double s) { savings += s; } Chapter VIII Making Object Methods and Encapsulation 341 342 Exposure Java 2012, PreAPCS Edition 06-25-12