Module 05 - Object-Oriented Programming PDF
Document Details
Uploaded by GorgeousQuatrain4929
Algonquin College
2024
Dave Houtman
Tags
Summary
These are lecture notes on Object-Oriented Programming. The notes cover what an object is, and how it differs from a static program. It explains why static members are unsuitable for certain programming tasks.
Full Transcript
MODULE 05: OBJECT-ORIENTED PROGRAMMING Professor : Dave Houtman Office Hrs : T: 16:00 – 16:20 (T323) F: 12:15 – 13:30 Em...
MODULE 05: OBJECT-ORIENTED PROGRAMMING Professor : Dave Houtman Office Hrs : T: 16:00 – 16:20 (T323) F: 12:15 – 13:30 Email: [email protected] © Dave Houtman 2024 1/38 5.0 What is an Object? We saw in the previous module that simple ‘static’ programs have limited applicability for real world tasks. Software needs to be able to reserve space programmatically, ‘on-the-fly’, as required by the requirements of the application. The static members of a program are incapable of this. At this point, it’s worth explaining what the word static means when used in our code: 1. The static members of a program are loaded into memory first, before execution. Thus ‘public static void main(…)’ signals that the main() method—or rather, it’s bytecode—is loaded into RAM first, prior to execution. Fields declared inside a static method, like studentFullName and age, are also treated as if they are local static values that are part of a particular class; 2. Static members are loaded at only one place in memory. Thus once a static method or field is loaded, every time it is referenced, execution refers back to the same place in memory. A static value can be reset, but it’s still just at the same place in memory, and so it can only hold one thing at a time for the class it’s declared in. …and this is why static members are unsuited for storing new information into RAM during execution. © Dave Houtman 2024 2/38 5.0 What is an Object? Objects solve this problem by allowing us to reserve space in memory using the new keyword. An existing class (a revised version of Student, whose code is shown below) is used as a template for that storage space, as follows: Student acStudent = new Student(); Here, we have assumed the Student class is already declared in code, looking like this: public class Student { String firstName; String lastName; String fullName; int age; int studentNumber;.. // Student methods go here. } © Dave Houtman 2024 3/38 5.0 What is an Object? Note the construction of each new object: You need to declare a The keyword new is needed to unique, valid, identifier instantiate the object Student acStudent = new Student(); Don’t forget the ; The type of the identifier should Construct a new object using the be the same type as the desired name of the class you wish to object (e.g. Student) instantiate, followed by ( ) As before, you may wish to separate out the declaration of the object from its assignment: Student acStudent;.. acStudent = new Student(); © Dave Houtman 2024 4/38 5.0 What is an Object? As for the Student class our code is based on, it will have the following features (not found in our earlier ‘static’ Student class): 1. the methods of the Student class are no longer declared static; and, 2. the properties of the new acStudent object—the term ’properties’ replaces ‘fields’ when used with objects—lie outside any methods. They become features of the new object, independent of any static features of the code public class Student { String firstName; String lastName; String fullName; int age; int studentNumber;.. // Student methods go here. } © Dave Houtman 2024 5/38 5.0 What is an Object? Used in this context, we can think of a class as acting like the template for the creation of multiple new objects. Each object is the instance of a class, something like the following: class RAM (Memory) object © Dave Houtman 2024 6/38 5.0 What is an Object? Once the class has been declared, it can be used to instantiate multiple objects: public class Cookie {…} Note that, as before, each object identifier must be unique. © Dave Houtman 2024 7/38 5.1 Constructors How do we initialize the features of each new object? There are two ways. First, provided the class contains one or more constructors, we can load the object’s properties directly at the time of creation. (Note that the constructor and class must have the same name.) public class Student { String firstName; String lastName; String fullName; int age; int studentNumber; public Student(String familyName){ lastName = familyName; }.. // additional Student methods go here. } © Dave Houtman 2024 8/38 5.1 Constructors Each constructor acts like a special kind of method. As with all methods, it takes an input as an argument, performs a process, and returns a (potentially void) value. When we instantiate a new object with an argument corresponding to the constructor’s parameter type, this value will be loaded in memory and stored with the object. 1. Pass the String variable "Wu". to the Student constructor…. Student acStudent = new Student("Wu");. 2. familyName is set equal to the String value "Wu".. public class Student {. String firstName;. String lastName;. // other declarations go here. public Student(String familyName){. 3. The object’s lastName property is set equal to the lastName = familyName; String value entered. So "Wu" is stored in the new object. } // additional Student // methods go here } © Dave Houtman 2024 9/38 5.1 Constructors Each constructor acts as a special kind of method. As with all methods, it takes an input as an argument, performs a process, and returns a (potentially void) value. When we instantiate a new object with an argument corresponding to the constructor’s parameter type, this value will be loaded in memory and stored with the object. 1. Pass the String variable “Wu". to the Student constructor…. Student acStudent = new Student("Wu");. 2. familyName is set equal to the String value "Wu". System.out.println("Family Name: " + public class Student { acStudent.lastName;); String firstName;. 4. The value stored in the object can be String lastName;. returned by calling objectName.property // other declarations go here public Student(String familyName){ 3. The object’s lastName property is set equal to the lastName = familyName; String value entered. So "Wu" is stored in the new object. } // additional Student // methods go here } © Dave Houtman 2024 10/38 5.1 Constructors So a constructor can be used to set the default features of an object at the time of it’s instantiation. cookie1 cookie2 public class Cookie {…} cookie3 cookie4 © Dave Houtman 2024 11/38 5.1 Constructors A class is not limited to a public class Student { single constructor; each String firstName, lastName, fullName; class can have multiple int age, studentNumber; constructors. For example, assume that // The Student 2-arg constructor public Student(String firstName, String lastName){ sometimes only a stud- this.firstName = firstName; ent’s first and last name this.lastName = lastName; were known at the time } the Student class was // The Student 4-arg constructor instantiated, while at public Student(String firstName, String lastName, other times all the stud- int age, int studentNumber){ ent’s information—first this.firstName = firstName; and last name, age and this.lastName = lastName; student number—were this.studentNumber = studentNumber; available. We could have this.age = age; two constructors to han- } dle these two scenarios: // additional Student methods go here } © Dave Houtman 2024 12/38 5.1 Constructors Objects are instantiated just as it they were in the previous example. When two Strings (only) are used in the constructor (the 2-arg constructor), only the first constructor is used. When two strings and two ints are used (the 4-arg constructor), the second constructor is called.. public class Student {. String firstName, lastName, fullName; Student firstStudent int age, studentNumber; = new Student("Suzi", "Wong");. public Student(String firstName, String lastName){ this.firstName = firstName;. this.lastName = lastName; Student secondStudent } = new Student("Vijay", "Patel", public Student(String firstName, String lastName, 19, 40992565); int age, int studentNumber){.. this.firstName = firstName; this.lastName = lastName;. this.studentNumber = studentNumber; this.age = age; } // additional Student methods go here } © Dave Houtman 2024 13/38 5.1 Constructors Note: public class Student { As before, multiple String firstName, lastName, fullName; declarations of the int age, studentNumber; same data type may be made on the same line. public Student(String firstName, String lastName){ When the parameter this.firstName = firstName; used to pass a value this.lastName = lastName; has the same identifier } as the property of the public Student(String firstName, String lastName, object, then this is int age, int studentNumber){ used to distinguish the this.firstName = firstName; two. ‘this’ indicates this.lastName = lastName; this (current) instance this.studentNumber = studentNumber; of the object. Hence this.age = age; this.age = age; } means: set this object’s age property equal to // additional Student methods go here parameter value (age) read in as an argument } of the constructor. © Dave Houtman 2024 14/38 5.1 Constructors Constructors are distinguished by their signature. This includes the type, order, and number of the constructor’s arguments; it does not include the identifier(s) used in the parameter list. No two constructors can have the same signature. So, while the following declarations would be legitimate in the Student class… public Student(int studentNum){…} public Student(String lastName, int studentNum){…} public Student(String firstName, String lastName, int studentNum){…} public Student(int age, String firstName, String lastName, int studentNum){…} public Student(String firstName, int age, String lastName, int studentNum){…} …these two constructors would trigger a compile-time error (Why?): public Student(String lastName, int age, int studentNum){…} public Student(String lastName, int studentNum, int age){…} © Dave Houtman 2024 15/38 5.1 Constructors When two or more constructors (or methods) have the same name but different paramet- ers, this is referred to as overloading. Some constructors with the same name may provide different services. One class which you are already acquainted with is highly overloaded: The Scanner class has 10 different signatures… …but you only use this one variation in this course Scanner input = new Scanner(System.in); © Dave Houtman 2024 16/38 5.1 Constructors You may have noticed earlier that we called a constructor with no-arguments: Student acStudent = new Student(); What happens when we instantiate a new object that lacks a matching constructor in its class? Generally, a compile-time error is flagged. But in the above case, where we have called on a no-arg constructor (one lacking any parameters, that isn’t already defined in the Student class), the JVM automatically supplies a default constructor for you, and assigns default values to its properties (unlike the static fields in our earlier classes). Data Type Default value Numeric data types (including int, char, byte, 0 short, double, etc.) boolean false Object (including String, Scanner, etc.) null © Dave Houtman 2024 17/38 5.1 Constructors Indeed, for all objects, any property not explicitly initialized during instantiation is set to the default values listed on the previous slide. Thus, if having set the student’s first and last name (only), we attempted to output their age or student number, the output will be ‘0’: public static void main(String[] args){... Student acStudent = new Student("Arjit", "Patel"); // age=0, studentNumber=0... System.out.println(acStudent.fullName + ", student number " + acStudent.studentNumber + ", is " + acStudent.age + " years old."); } © Dave Houtman 2024 18/38 5.1 Constructors We can also chain two or more constructors together using this(…). For example, assume a student may register without being assigned a student number or age. When this happens, as a way of signaling that the application is incomplete, students are assigned a default student number and age of -1. The two Student constructors would be written as: public class Student { String firstName, lastName, fullName; int age, studentNumber; public Student(String firstName, String lastName){ this (firstName, lastName, -1, -1) } public Student(String firstName, String lastName, int age, int studentNumber){ this.firstName = firstName; this.lastName = lastName; this.studentNumber = studentNumber; this.age = age; } // additional Student methods go here } © Dave Houtman 2024 19/38 5.1 Constructors The first constructor ‘chains’ to the second; it passes its two values (firstName and lastName) to the second constructor, along with the two default values. The second constructor—sometimes called the base constructor—does all the real work public class Student { String firstName, lastName, fullName; int age, studentNumber; public Student(String firstName, String lastName){ this (firstName, lastName, -1, -1) } public Student(String firstName, String lastName, int age, int studentNumber){ this.firstName = firstName; this.lastName = lastName; this.studentNumber = studentNumber; this.age = age; } // additional Student methods go here } © Dave Houtman 2024 20/38 5.1 Constructors The word this(…), means this object; the signature inside tells the compiler which constructor to chain to. So this(firstName, lastName, -1, -1) says: pass this information to the Student constructor having the parameters String, String, int, int, i.e. the 4-parameter constructor. public class Student { String firstName, lastName, fullName; int age, studentNumber; public Student(String firstName, String lastName){ this (firstName, lastName, -1, -1) } public Student(String firstName, String lastName, int age, int studentNumber){ this.firstName = firstName; this.lastName = lastName; this.studentNumber = studentNumber; this.age = age; } // additional Student methods go here } © Dave Houtman 2024 21/38 5.2 Launching the Program In keeping with the philosophies of modularization and encapsulation, it is advisable to separate the class that interacts with the user from the class used as the basis for new objects. The former class often has words like ‘Driver’, ‘Launcher’, ‘Starter’ or ‘Main’ attached to indicate that program execution begins at this point. In our example, this means that the class StudentLauncher will be responsible for prompting the user for the student’s information, instantiating objects based on this information, and displaying the results; the class Student only deals with those features typical of a real student. And as before, we still have the InputData class to handle the input of names and numbers. InputData StudentLauncher … // input Student data … // instantiate new Students // and output information … Student © Dave Houtman 2024 22/38 import java.util.Scanner; 5.2 Launching the Program public class InputData { static Scanner input = new Scanner(System.in); public static String inputName(…){ System.out.print(userPrompt); … return inputString; } public class StudentLauncher { public static int inputNumber(…){ public static void main(String[] args) { System.out.print(userPrompt); … String firstName = InputData.inputName( return inputNumber; "Enter your first name: "); } String lastName = InputData.inputName( } "Enter your last name: "); int age = InputData.inputNumber( public class Student { "Enter your age: "); String firstName, lastName, fullName; int studentNumber = InputData.inputNumber( int age, studentNumber; "Enter your studentNumber: "); Student( String firstName, String lastName){ Student student = new Student( this(firstName, lastName, -1, -1); firstName, lastName, age, studentNumber); } Student( System.out.println(student.fullName + String firstName, String lastName, ", student number " + student.studentNumber + int age, int studentNumber){ this.firstName = firstName; ", is " + student.age + " years old."); this.lastName = lastName; } this.fullName = firstName + " " + } lastName; this.age = age; this.studentNumber studentNumber; } } © Dave Houtman 2024 23/38 5.3 Public and Private Access Modifiers What if the object contains sensitive information which, while stored in the object itself, shouldn’t be made available to any user of that object? In such cases, the private access modifier limits access to that particular property; it can be seen (and used) only inside the object itself, but it is otherwise invisible outside of the class in which it is defined. public class Student { public String firstName, lastName, fullName; private String username; private String password; public int age, studentNumber; public Student(String firstName, String lastName, String username, String username, String password){ this.firstName = firstName; this.lastName = lastName; this.username = username; // initialize the username as usual this.password = password; // initialize the password as usual... }... } © Dave Houtman 2024 24/38 5.3 Public and Private Access Modifiers The private members of a class will be invisible outside the object itself. So the user of the class, in StudentLauncher, can’t call System.out.println(student.password); or, worse still, reset the password: student.password = "YouveBeenHacked"; Here, the password can only be set when the new Student object is instantiated (and in actual practice, it would probably be encrypted). But this applies not just to sensitive information, like passwords and bank account numbers, but even names, ages, and student numbers. If the object is to enjoy true encapsulation, we need to be able to limit access to the inner features of the object… © Dave Houtman 2024 25/38 5.4 Using Getters and Setters To protect the information public class Student { stored inside each object, private String firstName, lastName, fullName; make all of its properties private String username, password; private int age, studentNumber; private; provide public methods that allow access public Student(String firstName, …){ this.firstName = firstName; to these values in a …etc. controlled fashion. The } // other constructors go here methods that allow us to get (i.e. return) the value public String getFirstName(){ stored in an object’s return firstName; } property are called getters (or accessors); the methods public void setFirstName(String firstName){ this.firstName = firstName; that allow us to set these } properties are called setters (or mutators).... // include additional getters and setters here } © Dave Houtman 2024 26/38 5.4 Using Getters and Setters ⌘ Setters and getters allow the public class Student { users of a class to access private String firstName, lastName, fullName; object properties in a private String username, password; private int age, studentNumber; specified, safe fashion. For example, consider what // constructors go here // other getters and setters go here happens if the user inputs a null string into the first or last public void setFirstName(String firstName){ name field. A setter allows us if (firstName == null) throw new Exception("Invalid name entered"); to validate proper input, as this.firstName = firstName; // otherwise okay indicated in the code at right. } Note that Exceptions are NOT... // include additional getters and setters here part of this course. They will } be dealt with in your Level II Java course. This code is for explanation only and should NOT be emulated in your submissions this semester. © Dave Houtman 2024 27/38 5.4 Using Getters and Setters ⌘ Indeed, we can use the public class Student { setter to check for a variety private String firstName, lastName, fullName; of potential flaws in the private String username, password; private int age, studentNumber; input, as shown at right. // constructors go here So setters allow the // other getters and setters go here designer of the class to public void setFirstName(String firstName){ validate the data stored in if (firstName == null) objects (preventing bad // or firstName contains invalid // characters, or additional spaces, or data from getting recorded // unwanted carriage returns ,etc. in the object), while getters throw new Exception("Invalid name entered"); allow the designer to this.firstName = firstName; // otherwise okay (potentially) determine who } can view the data, and what... // include additional getters and setters here form its output takes. } © Dave Houtman 2024 28/38 5.4 Using Getters and Setters ⌘ Private methods can be public class Student { used internally whenever private String firstName, lastName, fullName; private … //etc. the class designer needs to public Student(String firstName, String lastName){ perform some task which setFirstName(firstName); // check before you set! should not be made visible setLastName(lastName); } to the user of the class… // Add constructors, getters and setters Again, note that checks of public void setFirstName(String firstName){ validateName(firstName); the sort seen at right are this.firstName = firstName; // otherwise okay NOT part of this course. } public void setLastName(String firstName){ validateName(lastName); this.lastName = lastName; // otherwise okay } private validateName(String name){ if (firstName == null) // or firstName contains invalid // characters, or additional spaces, or // unwanted carriage returns ,etc. throw new Exception("invalid name entered"); } © Dave Houtman 2024 29/38 5.4 Using Getters and Setters The fullName of the public class Student { student is a good example of private String firstName, lastName; where we would want a private … //etc. public getter and NO setter. public Student(String firstName, Since the fullName is String lastName){ entirely dependent on the setFirstName(firstName); firstName and lastName setLastName(lastName); properties of the Student } class, we don’t’ want to // Add constructors, getters and setters create a separate public public String getFullName(){ setFullName() setter; return (firstName + " " + lastName); this would encourage the } user to set a String value different than what would // Note: there should be no fullName setter be stored in the object’s // other getters and setters go here firstName and lastName } properties. © Dave Houtman 2024 30/38 5.4 Using Getters and Setters Setters can be used to set or reset properties after an object has been instantiated—the ‘second way’ to load objects we talked about earlier. So if we have all the data we wish to load up front, and an appropriate constructor to do so, we can use the first method. If we wish to instantiate an object first, and load its properties later, we can use the second method. public class StudentLauncher1 { public class StudentLauncher2 { public static void main(String[] args) { public static void main(String[] args) { Student student = new Student(); // no-arg String firstName = InputData.inputName( String firstName = InputData.inputName( "Enter your first name: "); "Enter your first name: "); String lastName = InputData.inputName( student.setFirstName(firstName); "Enter your last name: "); String lastName = InputData.inputName( int age = InputData.inputNumber( "Enter your last name: "); "Enter your age: "); student.setLastName(lastName); int studentNumber = InputData.inputNumber( int age = InputData.inputNumber( "Enter your studentNumber: "); "Enter your age: "); student.setAge(age); Student student = new Student(firstName, int studentNumber = InputData.inputNumber( lastName, age, studentNumber); "Enter your studentNumber: "); student.setStudentNumber(studentNumber); System.out.println(student.getFullName() + ", student number " + System.out.println(student.getFullName() + student.getStudentNumber() + ", is " + ", student number "+ student.getAge() + " years old."); student.getStudentNumber() + } ", is " + student.getAge() +" years old."); } } } © Dave Houtman 2024 31/38 5.4 Using Getters and Setters Notes about getters and setters: You must use proper identifiers in all getter and setter names All class methods, including getters and setters, should use camelCase formatting; The standard format for a getter is to append ‘get’ onto the front of the property it returns. Hence getFirstName() and getUsername(), again following camelCase formatting. Similarly for setters: setFirstName(), setUsername(), etc.; One exception to this rule is with getters that return a boolean value. The standard here is to replace ‘get’ with another verb like ‘is’, e.g. isPasswordCorrect() rather than getPasswordCorrect(); Getters should not alter the contents of the property whose value they return; All the members in a class should have public or private access modifiers, private for properties, public or private for methods, depending on whether they need to be visible to outside clients or not; Static members may be used in any class. But remember that static members are not instance members; they are loaded once at start-up, and any change to a static member will be visible to every other instance of that class. © Dave Houtman 2024 32/38 5.5 Why Use Static Members? Since objects are so powerful, the question then becomes: why does anything need to be static? The answer: ‘static’ still fulfils many programming requirements, including: Program execution begins in a static universe, before new instances of a class have been loaded: the JVM needs a static main() method to begin execution; Methods which are not instance-dependent do not need to be instantiated. For example, the Math class contains nothing but static methods, since e.g. the sin() method always performs the same task. Utility classes (such as Math) often have this feature; performing the same operations regardless of instance, they only need static, fixed methods to perform their function; It is sometimes necessary to store information in one location so that every instance can see it; in this case, that data must be static. For example, what if we wish to keep track of the number of instances created so that each object can see how many other objects are instantiated? Then we’d need a static variable that every class can talk to; As we’ll see shortly, when a value is declared constant (i.e. final) we often make it static. For example, if we need to use 2π in each object, why take up extra space reloading this value with each new object? Make it static final (and make the field private as well…why?), so then it exists only once in memory, not once in each object. © Dave Houtman 2024 33/38 5.6 Garbage Collection Objects occupy space in memory; once they're no longer needed, they should be deleted from memory. In early OOPLs (like C++) the programmer was responsible for this task; in modern languages (like Java), garbage collection automatically cleans up memory whenever an object is no longer used. memory location of cookie1 memory location of cookie2 'garbage collector' public class Cookie {…} cookie3 cookie4 © Dave Houtman 2024 34/38 5.7 Pseudocode and Flowcharts with Objects When using objects with pseudocode and flowcharts, we follow the same pattern as we saw in the last module. That is, external processes are represented with a special ‘box’ icon. Constructed objects can be signaled inside the declarations, or, if setters are used later indicate this as you would for any other methods. The following gives an example of this: start start Declarations Declarations int width, length int width, length Rectangle shape Rectangle shape width = InputData.getNumber( width = InputData.inputNumber(…) "Input rectangle width") shape.setWidth(width) shape.setWidth(width) height = InputData.getNumber( height = InputData.inputNumber(…) "Input rectangle height") shape.setHeight(height) shape.setHeight(height) shape.rotate() shape.rotate() output shape.getWidth() output shape.getWidth() stop stop © Dave Houtman 2024 35/38 5.8 Summary: What is an Object? An object is the instance of a class, that is, an allocation of memory based on the non- static members of the class it was instantiated from; The JVM relies on a constructor to tell it what default values to use when the object is loaded. Uninitialized values are set to 0. This may be changed afterward using setters (assuming the user has provided public setters for these features); Objects provide an intuitive way of handling code, since they operate as software abstractions of things that exist in the real world; Objects break down complexity by allowing each part of a project to be modularized Like things in the real world, objects hide the details of their implementation: you don’t need to know how a car works to drive it; The members of an object fall into two categories: properties store the state of the object, i.e. the values that characterize it at any point in time. Methods (which are distinguished from properties by their ‘()’) encode the behaviour of the object, i.e. the ways in which it can publicly interact with the user of the object (and for private methods, the operations that it performs internally). Alternately, one can think of properties and methods as the nouns and verbs that make up the statements of a program © Dave Houtman 2024 36/38 Questions 1. Explain why each term in the following declaration is needed. Specifically, what do the three references to a ‘scanner’ refer to? Scanner scanner = new Scanner(System.in); 2. How do default values in the instance of a new object differ from the static fields of classes? 3. What is output by the following code? public class Main { public class Person { public static void main(String[] args) { private int age = 25; Person person = new Person(); System.out.println(person.eyeColor); public String eyeColor; } } } © Dave Houtman 2024 37/38 Questions 4. What is wrong with the following code? Do these lead to compile-time errors or run-time errors? And how do you fix these problems? a) public class SatelliteLauncher { private int diameterOfEarth = 12473; // in km public static void main(String[] args) { int circumference = Math.PI * diameterOfEarth; System.out.println("The earth’s circumference is : " + circumference); } } b) public class Circle { private int diameter, circumference; // Note circumference = PI*diameter public int getDiameter(){ return diameter; } public void setDiameter(int diameter){ this.diameter = diameter; } public int getCircumference() { return Math.PI * diameter; } public void setCircumference(int circumference) { this.circumference = circumference; } } c) public Student(String first, String last) {this(first, last);} © Dave Houtman 2024 38/38