Phil Tayco San Jose City College Slide version 1.2 Updated Sep 9, 2019 Classes and Objects Phil Tayco San Jose City College Slide version 1.2 Updated Sep 9, 2019
Primitive Data Types All variables are defined with a data type and variable name int age = 21; double gpa = 3.9; Memory for age and gpa is instantly allocated and contents are initialized Process is automatically done because the language already knows these simple data types All variables in memory have a location Managing how these memory locations are used is the next step age 21 gpa 3.9
Memory References Memory locations can be referred to by other variables (in C/C++, this is called a “pointer”) A memory reference is essentially a variable that contains a memory address as its value The value refers to a memory location where information is stored When memory references are defined, the location it is pointing to must be reserved (a.k.a. memory must be “allocated”) Modern programming languages have “no pointers”, but in fact they are handling a lot of the pointer process automatically for you C and C++ gives you more memory management control, which can be both a blessing and a curse!
Memory References Memory references are useful when handling complex data In Java, memory reference management is automatically done by default when you use data types that are not primitive Exception: String data types are technically considered to be complex data types, but can be treated the same way as primitives Java manages memory references for simple and complex data types and does a lot of the behind the scenes work It is important to know the process that occurs behind the scenes as it will become useful to understand later with advanced concepts
Memory References When we declare a variable with a complex data type, the memory location it is referring to is yet to be defined Student me; me ?
Memory References To allocate the memory, we request it with the “new” keyword Student me = new Student(); When the compiler sees “new Student()” it uses what it knows a Student looks like and looks in memory for a location large enough to store that data 0x1234abcd is an example of a numeric location where the Student data could reside “me” is the variable that now refers to the location of the Student data. In Java, this is transparent to us, but we should know that this structure exists me 0x1234abcd (Student data)
Complex Data Types But how does Java know what “a Student looks like”? Integers and doubles are simple data types because they store one value. (age stores 21 and gpa stores 3.9) Conceptually, a Student can store much more types of information. Think of every Student that you may want to model in a program. Every Student has: First name Last name Age Gpa ID Each one of these elements of a Student is called a “property” (also called an “attribute”)
Complex Data Types These properties make up the template for defining a Student In the example, we declared a variable “me” whose data type is “Student” (this is the same as when we declared a variable “age” whose data type is an integer) We assigned age a value of 21 after we declared it. Similarly, we will want to assign values to me’s properties This means Student’s properties are like variables grouped together within (or “encapsulated”) the overall Student variable (“me”) me has its own first name, last name, ID, etc. As such, each property is defined like a variable
Complex Data Types public class Student { public String firstName; public String lastName; public int age; public int id; public double gpa; } These properties are defined in a separate Java file called a “class” The file is separate because a class is designed to be a “stand-alone” data type In true Object-Oriented design, a class is intended to be used by any number of other programs
Complex Data Types In another program (such as in the “main” function), we can assign values to these properties for the “me” variable In memory, technically the location where the Student data was allocated is found through the memory address – a process called “dereferencing” Student me = new Student(); me.id = 1234; me.age = 21; me.firstName = “Phil”; me 0x1234abcd firstName “Phil” lastName id 1234 age 21 gpa
Complex Data Types You can define as many different variables defined with primitive data types as memory allows (int x, int y, int z, etc.) Similarly, you can define as many different variables with classes (Student me, Student you, Student[] roster, etc.) Variables with primitive types are commonly referred to as just variables. A variable whose data type is a class is called an “object” Objects are seen as “instances” of a class. Creating objects is also called “instantiation” Object-oriented programming is the study of designing solutions primarily through the manipulation of such objects (variables with complex data types)
Accessing Properties When a class is designed with the data members public, a binding occurs between the code creating the object of that class and the class’ design Class example: public class Student { public String firstName; public String lastName; public int age; public int id; public double gpa; }
Accessing Properties Using that class, objects in other programs set property values directly: Student example = new Student(); example.firstName = “John”; example.id = 123; This makes the object and class code somewhat dependent on each other Changes in code on the use of the object are ok as they won’t affect the class code design More importantly, the class code shouldn’t be aware how it’s used! The class is simply providing capabilities to object creators.
Programming Exercise 1 Create a class that models a simple Car For your Car class, create 5 properties that will utilize at least 1 String, 1 int and 1 double. The properties are: Make (e.g. “Toyota”) Model (e.g. “Corolla”) Year (e.g. 2016) Price (e.g. 15000.99) Some other property of your choosing Next, write a main program that creates at least 2 Car objects and assigns values to each one’s properties You can hard code the values in the code and display them on the screen – the purpose of this exercise is to get you used to creating classes
Accessing Properties The relationship from this exercise and example can be referred to as “high coupling” or “weak encapsulation” Weak encapsulation means that the property information is not hidden because it is available for all to use (they are public) Is this high coupling bad? What if the code in main changes (example.id = 456;), does that impact the code in the class? What about the other way? What happens if we change any of the code in the class. Does it affect the code in main?
Accessing Properties Absolutely! public class Student { public String first_name; public String lastName; public int age; public String id; public double gpa; } These simple code changes affects the example object example.firstName has to change to example.first_name example.id = 123 has to change to example.id = “123”
Accessing Properties In small amounts of code, this can be manageable, but as programs get larger and object use increases, any change in class code design has more downstream effects Property usage is also a highly performed activity – programs are fundamentally designed to manipulate the variable values and make logical decisions from them It is also hard to predict what complex programs actually need as they evolve (i.e. class designs change often) Classes are also supposed to be stand-alone. New programs using the class may have different needs than as the class originally was designed As requirements change, data types used will evolve
Strong Encapsulation Because class properties have such high usage and evolution, another approach is to hide that information from other programs public class Student { private String firstName; private String lastName; private int age; private int id; private double gpa; } This now means any object created as type Student cannot directly access the properties (example.id = 123 would result in a compile error)
Strong Encapsulation How are property values manipulated if they are marked as private? Something else has to be marked as public… In order to see how that is typically done, we must first discuss another aspect to all class designs To this point, our classes have properties that define “what objects of that class type will have” In addition, we can define “behaviors” that define “what you can do with objects of that class type” Set the Student’s name Check if the Student has a passing grade Determine if the Student is an adult based on their age These behaviors are also referred to as “methods” and they define actions
Class Methods We’ve already seen code that define actions such as “calculateArea” or “println” These actions are defined in the form of a function. Recall that a function is defined with 3 parts: function name, return type and input parameters public double calculateArea(double length, double width) { return length * width; } This function is defined with the name “calculateArea”, a return type of “double” and has 2 input parameters that are each “double” data types
Class Methods We call the definition of a function a “function signature” and all signatures have these 3 elements Within the function contains the code for performing the overall action it is intended to define We learned that such code is also designed to be stand-alone and hidden. This means whomever calls the function with their code, they don’t see what the code actually does (nor should they!) Key concept: a function caller should only know how to use a function properly and that it performs as expected We can take advantage of this by defining functions in classes designed to handle property value usage
Class Methods public class Student { private String firstName; public void setFirstName(String f) firstName = f; } In this example, the method signature is “setFirstName”. It takes a String as an input parameter and returns nothing (return type is void) Within the function, “f” is a local String variable initialized by the input value where the function was called The goal of this method is to set the firstName property to a given value (stored in f)
Class Methods Typical questions arise from this approach How is this function called? Where and how is “firstName” used? Remember that these functions live within the context of a class A class is used when an object is instantiated of its type Once an object is created, anything defined as public within the class design is usable and will apply to that specific object
Class Methods Student me = new Student(); me.setFirstName(“John”); In this example, an object “me” is created of type Student The only thing defined as public in the Student class is the “setFirstName” method When the method is used, it will be in the context of a created object – this means in this case, the setFirstName method will be applied to the “me” object Since the method is a public function, we use it like a function call, sending in a String and not expecting a return value because of the way the method signature is defined
Class Methods When the method is called, “John” comes in as an input value that will be assigned to the “f” variable in the setFirstName function public void setFirstName(String f) { firstName = f; } Now the important part: the only line of code in the method is “firstName = f;”. Where is firstName defined? Since it is not defined within the function, we have to look outside the function but still within the code module the function is defined
Class Methods That code module is the class itself! public class Student { private String firstName; public void setFirstName(String f) firstName = f; } That code module is the class itself! This means firstName is accessible to all functions defined within the class Now note that firstName is treated like a variable – we call it a class property, but it is essentially a variable By itself, firstName is definition. It is not a physical variable, until when…?
Class Methods …when an instance of the class is created! “firstName” doesn’t become a physical element in memory until “Student me = new Student();” was created Once that object was instantiated, me.firstName = “John”; could be done to assign “John” to the firstName property of the “me” instance But remember, we made firstName private, so that line of code is not allowed setFirstName is a method that is public, so we will use that By calling the function setFirstName(“John”): “John” is used in the function (through f) f is assigned to the variable firstName firstName represents the property of the me object (because we called it with “me.setFirstName(…”)
Class Methods This approach can be used with all class properties public void setGpa(double g) { gpa = g; } Some questions to note: “gpa” property name is part of the function name “setGpa” – what would the function name be for the id or lastName properties? The input parameter type is “double” which matches the gpa property data type definition. What would the input parameter types be for id and lastName? Why is the return type void? Could the return type be something else? If so, what could it signify?
Class Methods This approach promotes code reuse as well. If we create multiple objects, the same code is used within the context of each object: Student one = new Student(); Student two = new Student(); one.setFirstName(“Susan”); two.setFirstName(“Alex”); One and two are physically two separate objects with their own property values Both are using the same code instructions to set their individual firstName properties respectively These particular methods are frequently used and commonly referred to as “setters” or “mutators” – they are functions designed to change object property values
Class Methods Could you create set methods that change more than one property at a time? Yes! public void setName(String f, String l) { firstName = f; lastName = l; } What are pros/cons to doing so? Remember, any function created doesn’t always have to be used… Mutators are needed for changing object property values. What about when we need to view the data?
Accessing Data Previously, we could look at an object’s property value at any time directly: System.out.println(me.firstName); However, the firstName property is now private We need another way to retrieve that value Put another way, we need a “method” that is designed to “return” the firstName value to us This leads to designing another function. Based on the information here, what would the method signature for seeing the object’s firstName value?
Accessing Data Remember the 3 parts to the function signature: name, input parameter types and return type public String getFirstName() { return firstName; } The name of this function (which also states its purpose) is appropriately entitled “getFirstName” The return type is a String meaning that when the function is called, we will get what represents the firstName of the Student object as a String Why are there no input parameters?
Accessing Data Just like with the set methods, these get methods are designed to be used for each class property Because the value coming back is through a return value of a function, the get methods are designed to return one property value The return type in this example is a String which matches the definition of firstName in the class. This usually is the case, but remember: The class is encapsulating the definition of the firstName property. This means we can change the name and the type at any time (what would we have to change if we did that?) There are usually no input parameters with get methods because their job is to return existing (and known) information. No new information from the object method call is needed to perform this action
Setters and Getters Like setters/mutators, these functions are commonly referred to as “getters” or “accessors” You typically see a get and a set function for each property (a class with 4 properties will usually have 4 accessors and 4 mutators) Their function signatures usually follow a pattern based on the property name and its data type Some classes may not want to have certain accessors/mutators defined – this will depend on the class designer’s intent of use Any number of setter functions can occur. Typically you see one get function per class property
Changing Design Why go through the of creating set and get methods when making the properties public seems so much easier? Recall the dependency between the modules and when class code changes – the change impacted the code in main in our previous examples If we wanted to, we can change a property name or a property data type, without impacting main because that code is marked as private
Changing Design We changed the property from firstName to first_name public class Student { private String first_name; public void setFirstName(String f) first_name = f; } We changed the property from firstName to first_name Because of that, we also had to change its use in the setFirstName method Important: the main program still calls the method with me.setFirstName(“John”); - this code does not change! (it doesn’t even know the code in method changed!)
Changing Design This puts in a foundation such that your class code can now change with minimal to no impact to other programs using it This emphasizes the importance of a function signature – because it is public (it is the interface for the application programmer), once it is in use, great care must be taken if you decide to change it This also emphasizes trying to get the signature well defined before releasing for use Once established, code changes within the methods and anything marked private can be done within the class code file itself
Programming Exercise 2 Update your Car class so that all the properties are now private Add the appropriate set/get methods to your class Update the main program to have each Car object call all set/get functions you created to test your code