Java Software Solutions Chapter 4 Objects Revisited 1 Objects Objects are created from classes. A class is a template that defines the attributes and behavior of the objects it describes. The values of an object’s variables describe the object’s attributes. The “variables” mentioned here refer to the instance variables defined in the object’s class. The collection of attributes ( values stored in the instance variables) define an object’s state of being. The methods that can be invoked using the object define the object’s behaviors. Here “methods” refers to the methods defined in the object’s class. 2 Another Way to Say It Classes are what you create when you write a program. Objects are created in the computer during program execution. When your program is executing, your code instantiates objects whose state is stored in the object’s instance variables and whose behavior (changes in the object’s state) is manipulated using the object’s methods. The only state and behavior an object can exhibit is that defined in the classes you wrote. 3 What Happens in Memory During Program Execution Each object has its own state. Each object has memory allocated for its own instance variables. All objects of a particular class can access the same methods to control their behavior. The code for a class’s methods exists for the use of any object from the class and only needs to be stored one place in memory. An object’s behavior often modifies its state. When an object’s method executes, it often results in a change in the values stored in its instance variables. 4 Objects can Represent Items that are Intangible Software objects often represent tangible items such as people, cars, etc. (things you can touch). But objects can represent intangibles such as error messages, mathematical concepts and operations, etc. A common mistake for programmers new to object-oriented programming is to limit their possibilities for creating objects to tangible entities. 5 Classes An object is defined by a class A class represents a pattern from which an object is created during program execution. In general, no space to store data values is reserved in a class. To allocate space to store data values during program execution, we must instantiate one or more objects from the class. Each object is an instance of its class. Each object has space in memory for its own data, which is why each object can have its own state. 6 Anatomy of a Class A class contains: declarations of the data (instance variables) that will be stored in each instantiated object. declarations of the methods that can be invoked during program execution by using an instantiated object. Methods are invoked using the commands of the form: objectName.methodName(arguments) Collectively, the data and methods are referred to as the members of the class. 7 Demonstration Program CountFlips.java CountFlips.java (page 213 of our text) The CountFlips program simulates the flipping of a coin 1000 times to see how often it comes up heads or tails. Note that the CountFlips class contains the static method main(). Objects cannot be instantiated from this class. Rather the main() method exists for the purpose of controlling execution by instantiating a Coin object and using that object to invoke methods defined by the Coin class. 8 Demonstration Program Coin.java Coin.java (page 214 of our text) The Coin class has two integer constants, HEADS and TAILS and one integer variable named face. The first method is a constructor that is used in the main() method of CountFlips to instantiate a Coin object. The remaining methods, flip() and isHeads() are invoked by CountFlips’ main() method to flip the Coin object and to check if heads or tails comes up. 9 Instance Data In the Coin class, the constants HEADS and TAILS and the variable face are declared inside the class, but not inside any method. By being declared at the class level (not within any method), these variables and constants can be referenced by any method of the class. The location at which a variable is declared defines its scope, which is the area within a program in which that variable can be referenced. Variables declared with class scope are called instance data because memory space is created for each instance (instantiated object) of the class. 10 String Concatenation and Objects When an object reference variable is used as an operand of the string concatenation operator (+), that object’s toString() method is automatically called to get a string representation of the object. If no toString() method is defined for a particular class, a default version is called that returns a string that contains the name of the class, together with other information. It is usually a good idea to define a specific toString() method for a class. 11 More on Class Level Variables Java automatically initializes any variables declared at the class level. Numeric variables such as int and double are initialized to zero. However, it is good practice to initialize variables explicitly (usually by using a constructor) so that anyone reading the code will clearly understand the intent. 12 Demonstration Program FlipRace.java FlipRace.java (on pages 217 & 218 of our text) FlipRace instantiates two Coin objects. Note that the flip() method is called with coin1 and then again with coin2. Even though the same method is called both times, it is only the Coin object that invoked the method that is flipped. Also, note that the instance variables count1 and count2 are explicitly initialized to zero, even though that would have happened automatically. 13 Unified Modeling Language (UML) Diagrams UML Class Diagrams Consist of one or more classes, each with three sections for the class name, attributes, and methods. Example using the FlipRace program: Coin FlipRace 1 2 face : int main(args : String[]) : void flip() : void isHeads() : boolean toString() : String 14 Explanation of UML Class Diagram This is a diagram representing two classes. A FlipRace class with no attributes and just a main() method. A Coin class with an integer attribute named face and three methods, flip(), isHeads(), and toString(), each of which takes no arguments. flip() returns void, isHeads() returns a boolean value, and toString() returns a String. Coin FlipRace 1 2 face : int main(args : String[]) : void The line between the class diagrams represents an association that shows FlipRace associated with two Coins. flip() : void isHeads() : boolean toString() : String 15 Comments about UML Diagrams UML diagrams always show the type of an attribute (instance variable) and the parameters and return value (after a colon) of the methods. UML is intended to be language independent, thus its syntax is not specific to Java or any other language. UML is the world’s most popular notation for the design of object-oriented software. 16 UML Object Diagrams A UML object diagram consists of one or more instantiated objects. A snapshot of the objects at a given point in the executing programs. Example using the FlipRace Program: coin1 : Coin face = 0 coin2 : Coin face = 1 17 Additional Comments about UML Diagrams UML notation is primarily a language-independent mechanism for visualizing and capturing the design of a program before it is written. It not intended to describe a program after it is written. A common mistake of beginning (and some experienced) programmers is to start writing their programs before doing the design work. We will see additional UML notations that will help us visualize the classes and objects we use in our programs. 18 Two Ways of Thinking about Objects When designing and implementing an object: We need to think about how the object works. Define the variables that will be held in the object and write the methods that make the object useful. When designing a solution to a larger problem that involves multiple objects: We need to think about how objects in the program will interact. At this level, we only need to think about the services an object provides, not about the details of how those services are provided. 19 Focusing on the Larger Picture Objects provide a level of abstraction that allows us to focus on the larger picture when we need to. For the abstract to work, we must maintain the boundaries between objects. Only the methods within an object should have direct access to the variables in that object. We should make it difficult for the code outside of a class to change the value of a variable that is declared inside the class. 20 Encapsulation and Visibility Modifiers An object should be encapsulated from the rest of the system. An object should interact with other parts of the program (methods in other objects) only through the specific set of methods which define the services the object provides. An object’s methods define the interface between that object and the program that uses it (i.e., the methods in other objects within the program). 21 Accomplishing Encapsulation We accomplish object encapsulation using modifiers. Modifiers are reserved words in Java. Various modifiers will be discussed at appropriate points in this course. All modifiers are summarized in Appendix E. Some Java modifiers are called visibility modifiers because they control access to the members of a class. 22 Visibility Modifiers The reserved words public and private are visibility modifiers that can be applied to the variables and methods of a class. If a member (variable or method) of a class has: public visibility It can be directly referenced from outside of the object. private visibility It can be accessed only by the methods of the class. This makes the objects created from that class selfgoverning. 23 Public Variables Violate Encapsulation Instance data should be defined with private visibility. So while it can still be used anywhere inside the class definition, it cannot be referenced externally. If instance variables were declared public, they could be directly modified by other object’s (and possibly other program’s) methods during program execution. Which would make it much easier for hackers to obtain information 24 Methods are Usually Public An object that needs to use the services of another object is called a client of the other object. Methods that provide services to the clients of a class must be declared with public visibility so they can be invoked by the client. The only purpose of a private method is to help the other methods of the class do their job. Such methods are referred to as support methods. 25 Effects of Public and Private Visibility public private Variables Violate Encapsulation Enforce Encapsulation Methods Provide Services to Clients Support other methods in the class 26 Public Visibility for Constants Giving constants public visibility is generally considered acceptable. Because constants cannot be changed, they do not need to be protected from malicious attempts to change them. However, sometimes constants need to be protected from viewing. If so, they can be declared as private. 27 Additional Comments Regarding Visibility A client can still access or modify private data by invoking public service methods. A class must provide public service methods for valid client operations. The code for those methods must be carefully designed to permit only appropriate access and valid changes. UML diagrams reflect the visibility of a class member with special notations. A member with public visibility is preceded by a plus sign ( + ). A member with private visibility is preceded by a minus sign ( - ). 28 Higbee’s Program 3B UML Class Diagram Program3B QuizAverage 1 +main(args : String[]) : void * - fullName : String - quizAvg : double + getData( ) : void - getMessage( ) : String + toString( ) : String Indicates a one to many association in which multiple quiz averages can be calculated and displayed. 29 Methods A class contains: declarations of the data (instance variables) that will be stored in each instantiated object. declarations of the methods that can be invoked during program execution by using an instantiated object. Methods are invoked using the commands of the form: objectName.methodName(arguments) 30 Anatomy of a Method The header of a method includes: the type of the return value the method name, possibly preceded by some modifiers (public, static, etc.) within parentheses, a list of parameters that the method accepts when it is invoked The statements that make up the body of the method are defined in a block delimited by braces. See the syntax diagram on page 224. 31 Invoking a Method The method declaration consists of the method header and the method body. The declaration is written within the method’s class. A method invocation is the code that causes the method to execute. The invocation may be in the same object as the method or in a different object belonging to a different class. If an invoked method is part of the same object, only the method name and parentheses enclosing any actual parameters need be used to invoke it. If an invoked method is part of an object from a different class, that object’s name must be used followed by a period, the method name, and parentheses enclosing any actual parameters. 32 Flow of Control Following Method Invocations Figure 4.8 shows how a method is invoked from an object in the same class doThis() invoking helpMe() and from a different class main() invoking doThis(). a class main( ) obj.doThis() object from another class doThis( ) helpMe( ) helpMe() 33 Driver Programs and main( ) The class that contains the main( ) method is usually a driver class (often referred to as a driver program). No object is ever instantiated from the class. All the class does is instantiate and use objects from other classes created as part of the overall application. Sometimes driver classes are created for the sole purpose of testing the other classes. 34 The Banking Demo Program Banking.java on page 226. An example of a driver program. Calls the constructor and other methods in the Account class. Account.java on pages 227-229. Methods of the Account class perform various services on a bank account. Contains examples of “get” methods and a toString() method. 35 UML Object Diagrams for Objects of the Banking Program acct1 : Account acct2 : Account - name = “Ted Murphy” - acctNumber = 72354 - balance = 102.56 - name = “Jane Smith” - acctNumber = 69713 - balance = 40.00 acct3 : Account - name = “Edward Dempsey” - acctNumber = 93757 - balance = 759.32 36 The Return Statement The return type specified in the method header can be a primitive type, a class name, or the reserved word void. The return statement consists of the reserved word return followed by an expression whose value is returned. The data type of the expression must be consistent with the return type in the method header. For example, you can’t return an integer if the return type shown in the method header is String. A method that returns a value must have a return statement. 37 When can you Not have a Return Statement A method that does not return a value does not usually have a return statement. Such a method will have void as its return type in the method header. However, a method with a void return type may contain a return statement with no expression. A method with no return statement will automatically return when the end of the method is reached. 38 Other Considerations Regarding return Constructors do not have a return type at all. Not even void. A return value can be ignored. Often the value returned to a calling statement is used in some way. Such as being assigned to a variable or used in a control statement (e.g., when a boolean value is returned). In other cases, the value returned is simply ignored. 39 Parameters The parameter list in a method header specifies the types of the values that are passed and the names by which the called method will refer to those values. The names of the parameters in the header of a method declaration are called formal parameters. The values passed into a method when it is invoked are called actual parameters. 40 Invoking versus Declaring Beginning students are often unclear about the difference between a method declaration and a method invocation. A method declaration is located in the class to which the method belongs and consists of the method header and method body. This is “the method”. A method invocation is often in a different class and consists of the method name (often preceded by an object name and a period) and parentheses enclosing the actual parameters. The method invocation does not include a method body. 41 Formal and Actual Parameters Formal parameters are identifiers that serve as variables inside the method The values in the formal parameters come from the actual parameters in the method invocation. If an expression is used as an actual parameter, it is fully evaluated before the method is called and the result is passed to the formal parameter. The formal parameters and actual parameters must correspond in number and type including the order they occur in their respective parentheses. 42 Constructors When we define a class, we usually define one or more constructors to help us set up an object when one is instantiated during program execution. A constructor differs from a regular method in two ways: A constructor has the same name as the class. A constructor does not have a return type specified in the method header (not even void). 43 Using Constructors A constructor is generally used to initialize the instance variables of a newly instantiated object. We don’t have to define a constructor for every class. Each class has a default constructor that takes no parameters and is used if we don’t provide an explicit constructor. This default constructor generally has no effect on the newly created object. 44 Local Data versus Instance Data A variable that is declared inside a method is called a local variable. As opposed to an instance variable that is also declared inside a class, but not in one of the methods. The scope of a local variable is limited to the method in which it is declared. As opposed to an instance variable whose scope is the entire class (any method in the class can refer to it). 45 Local Variables It is possible to declare a local variable inside a method using the same name as an instance variable declared at the class level. When you use the name inside that method, it refers to the local variable. Anywhere in the class outside that method, the name would refer to the instance variable. Our text suggests that you avoid doing this. 46 Formal Parameter Names The formal parameter names in a method header serve as local variables. They don’t exist until the method is called, and they cease to exist when the method is exited. 47 Method Overloading In object-oriented languages, you can use the same method name with different parameter lists for multiple methods within the same class. This technique is called method overloading. Method overloading is useful when you need to perform similar methods on different types of data. For example, you may want to compute the weekly pay for both salaried and hourly employees. 48 Method Signatures A method’s name along with the number, type, and order of its parameters is called the method’s signature. Two methods can have the same name (can be overloaded) as long as something else is different in the signature. Note that the return type of a method is not part of the method signature. Two overloaded methods cannot differ only by their return type. 49 Constructors and Overloading Constructors are a primary candidate for overloading. Recall that constructors always have the same name as the class. Thus the only way a class can have multiple constructors is to overload them. By providing multiple versions of a constructor, we can provide several ways to initialize an object’s instance variables. 50 Example of Method Overloading The Die Class SnakeEyes.java on page 236. Provides the main() method. Calls two different overloaded Die() constructors. Die.java on pages 236-237. Contains the overloaded constructors: public Die( ) public Die (int faces) 51 Method Decomposition Whenever a method becomes large or complex, we should consider decomposing it into multiple methods to create a more understandable class design. First, however, we must consider how other classes and objects can be defined to create better overall system design. In object-oriented design, method decomposition must be subordinate to object decomposition. 52 UML Class Diagram for the PigLatin Program PigLatin 1 1 PigLatinTranslator + main (args: String[]) : void Note: translating an entire sentence into Pig Latin in one big method would be long and difficult. Instead the translate() method is decomposed into several support methods. + translate (sentence : String) : String - translateWord (word : String) : String - beginsWithVowel (word : String) : boolean - beginsWtihBlend (word : String) : boolean 53 The PigLatin Program PigLatin.java on page 238. Contains main(). Assumes the input will have no punctuation. PigLatinTranslator.java on pages 240-241. The translateWord(), beginsWithVowel(), and beginsWithBlend() methods are declared with private visibility and exist only to help the public translate() method, which is the only true service method in the PigLatin class. The task of translating a sentence has been decomposed into these four methods. 54 Object Relationships Classes, and their associated objects, can have particular types of relationships to each other. Now, we consider the idea of a general association. We then extend that concept to include associations between objects of the same class. Then we will explore aggregation, in which one object is composed of other objects. 55 Association Two classes have a general association when those classes are “aware” of each other. Objects of those classes may use each other for the specific services that each provides. This is referred to as a use relationship. An association relationship is intended to be very general and therefore very versatile. Associations will be introduced throughout the course. One association could be an Author object writes a Book object. 56 UML Diagram for an Association The association connections between two classes in a UML diagram can be annotated with comments referred to as adornments. Associations can have a multiplicity associated with them. On a UML diagram, the asterisk can be used to indicate a general zero-or-more value. An appropriate range of values could be given, such as 1...5. 57 Association between Objects of the Same Class Some associations occur between two objects in the same class. A method of one object takes as a parameter another object of the same class. The operation performed often involves the internal data of both objects. An example is: str3 = str1.concat(str2); The Rational.java and RationalNumber.java programs on pages 243-249 provide other examples. 58 Aggregation Some objects are made up of other objects. A car is an aggregation – it is composed of other objects (a car has a chassis). Aggregation can be described as a has-a relationship. An aggregate object is any object that contains references to other objects as instance data. The StudentBody.java , Student.java and Address. java programs on pages 250 - 253 demonstrate an aggregation. 59 The UML Representation of an Aggregation 2 StudentBody 1 Student - firstName : String - lastName : String - homeAddress : Address - schoolAddress : Address + main (args : String[ ]) : void Address - streeAddress : String - city : String - state : String - zipCode : Long + toString( ) : String 60