JAVASCRIPT: OOP



What is OOP? What is an Object?

Object oriented programming is the process of creating your own reference type variables. An object is a representation of any real world thing. For example, civil engineers working on simulating traffic flow might need to represent cars and traffic lights. Game designers might need to represent missals and attackers. Cell phone developers often need to reference dates, times and locations (GPS coordinates). Each of these items would be an object. In OOP, programmers create files for each object and then put the files together to make a full program.

Objects have two main parts – properties and actions. Properties qualities that an object possesses and actions are things that the object can do. The designer of an object needs to determine what properties and actions the objects of the class will need to perform the necessary jobs. In the case of the car object that the civil engineers need, we might store properties of make, model, year, color, and number of passengers. Meanwhile, each car will need to move forward, backward, stop and turn (both right and left). We often use something called UML (Unified Modeling Language) to display the design of a class. UML is a comprehensive set of rules for designing and modeling, but will only use a subset of this information. In a basic UML diagram, we will need to state the variables with types (properties) and the methods with return types and parameters (actions). So, for our car class, the resulting UML diagram looks as follows:
Car

String color;
String make;
String model;
int year;
int numPassengers;

move(float distance);
turn(float degrees);
stop();

JavaScript Objects

Objects in JavaScript are created using the name/value pairings. A name value pairing sets a property name to its values. Values for strings should be encased in quotes, while boolean and numeric values should not. Similar to CSS, names and values are separated by colons. Subsequent properties are separated by commas. All pairs are enclosed in curly braces to denote the start and end of the object.
var today={"month":10, "day":31, "year":2015};
To output information from the created object, use the dot(.) operator. Any property of the object can be accessed by using the objectName(variable).propertyName. So, to output the month of the above date:
document.write(today.month);
Creating objects in this way is good for data storage (JSON), but can be tedious when trying to use the properties of a class to create multiple objects. Additionally, it is often desired to have methods that can operate on the object. For these reasons, we typically create a class when considering OOP. A class is a blueprint for an object that stores the properties (variables) and actions(methods) that the object will have.

Creating a JS Class

To create a class in javascript, we type class and the name of the class. The class name usually starts with a capital letter and uses camelCasing for readability when necessary. The body of the class (methods and such) are contained in a set of curly braces.
class Date{
    //code goes here
}

Constructors

Most classes have a special method called a constructor. The purpose of a constructor is to give values to all of the variables of an object. JavaScript constructors use use the keyword this to denote instance variables. An instance variable is a property of the class, or a variable, that stores information. Each object created from a class will have the same instance variables, but will hold its own value for each variable. Iin the example of the car, we may have two Car objects, c1 and c2. c1 might represent a 2014 Silver Honda Accord, while c2 might represent a 2019 Green Nissan Sentra. Each instance(object) of the class has a year, color, make and model, but each instance stores its own values in those variables. When creating a constructor method, the name of the method is constructor. A constructor will typically have parameters to set the values of each variable. Inside the constructor, the parameter variables are assigned to the instance variables. In this example, they are named the same. It is the use of the 'this' keyword that lets the computer know the difference between the instance variable and the parameter variable.
constructor(month, day, year){
    this.month=month;
    this.day=day;
    this.year=year;
}
JavaScript does not allow method overloading (writing multiple methods with the same name but different parameters), which is a common practice in Java OOP for creating constructors. However, they allow for a variety of constructors by allowing default values to be assigned to a parameter in the function header. In the example below, the contructor is expecting to take 3 parameters. If it is called with no information, the default values for month, day and year will be assigned. If it is called with one parameters, the default values for day and year will be assigned, and so on.
constructor(month=1, day=1, year=1970){
    this.month=month;
    this.day=day;
    this.year=year;
}
Use examples with different calls to the constructor:
var d1=new Date(); //sets date as 1/01/1970
var d2=new Date(5); //sets date as 5/01/1970
var d3=new Date(9,26); //sets date as 9/26/1970
var d4=new Date(12,25,2019); //sets date as 12/25/2019
Finally, JavaScript does not allow instance variables to be private, a key element in most object oriented programming. Private instance variables are important to programmers so that users of the class don't have direct access to the variables. Many JavaScript programmers try to imitate private variables by starting their instance variable names with an underscore.
constructor(month=1, day=1, year=1970){
    this._month=month;
    this._day=day;
    this._year=year;
}

Getter and Setters

Most classes, because they are utilizing private instance variables, rely on getter and setter methods to access their variables. This allows programmers to limit the access users have to these variables either in getting a value or setting a value. For example, we wouldn't want people to be able to set the color of a traffic light to blue. So, our setter method would verify that the value sent in was either red, yellow or green. Getters provide access for a user to retreive the value of a variable. We might not provide a getter for the password to a bank account!

Below is a set of JavaScript getters and setters for the date class. Notice that all getters are written as anyone should be able to access the values in month, day or year. Also, notice the use of conditions and returns in the setters if the parameter value is not viable.
get month(){
    return this._month;
}
get day(){
    return this._day;
}
get year(){
    return this._year;
}
set month(month){
    if(month>=1 && month<=12){
        this._month=month;
        return true;  //value was set
    }
    return false; //value was not changed
   
}
set day(){
    if(day>=1 && day<=31){
        this._day=day; //ignoring days per month for simplicity of example
        return true;
    }
    return false; //value was not changed
}
set year(year){
    this._year=year; //no need to check years, though we could make sure its positive
}
      

Other Methods

Objects, as seen in the Car class above, often have other methods associated with them. For example, a trafficLight class may need a changeColor() method set up that will alter the colors from green to yellow to red and back to green. These methods can be simply written in a JavaScript class like any other method. One method, that should be in every class is the toString method. The toString method is designed to return a string showing the state of the object (the values of all instance variables at that moment. Below are some methods that might be useful in our Date class.
toString(){
    return month+"/"+day+"/"+year;
}

euroFormat(){
    return day+"/"+month+"/"+year;
}
nysqlFormat(){
    return year+"-"+month+"-"+day;
}
addYears(numYears){
    this._year+=numYears;
}

Using Objects in Code

Constructors are called using the keyword new and are assigned to a variable. When this happens, the varible is created as an object with the properties defined in the constructor and the values that are sent in as parameters. This method of creating an object allows variables to be used as property values if desired.
var today = new Date(9, 10, 2020);

Any methods in the class, can then be called from the object that we created...
today.addYears(2);
window.alert(today.toString()); //outputs 9/10/2022

Completed Class and Use

When we put it all together in a program, we get a code file that looks like this...
public class Date{
    constructor(month=1, day=1, year=1970){
        this.month=month;
        this.day=day;
        this.year=year;
    }
    
    //GETTERS
    get month(){
    return this._month;
    }
    get day(){
        return this._day;
    }
    get year(){
        return this._year;
    }
    
    //SETTERS
    set month(month){
        if(month>=1 && month<=12){
            this._month=month;
            return true;  //value was set
        }
        return false; //value was not changed
       
    }
    set day(){
        if(day>=1 && day<=31){
            this._day=day; //ignoring days per month for simplicity of example
            return true;
        }
        return false; //value was not changed
    }
    set year(year){
        this._year=year; //no need to check years, though we could make sure its positive
    }
    
    //OTHER METHODS
    toString(){
        return month+"/"+day+"/"+year;
    }
    
    euroFormat(){
        return day+"/"+month+"/"+year;
    }
    nysqlFormat(){
        return year+"-"+month+"-"+day;
    }
    addYears(numYears){
        this._year+=numYears;
    }
    
}//end of class

//main program code
var today = new Date(9, 10, 2020);
today.addYears(2);
window.alert(today.toString()); //outputs 9/10/2022

Arrays of Objects

Objects in Arrays As in other languages, JavaScript arrays can store objects as well. The objects in an array can be named or anonymous objects and can be accessed by simply iterating over the array structure and using either object property names or method calls.
    var gameDates=[];
    gameDates.push(new Date(10,3,2020));
    gameDates.push(new Date(10,10,2020));
    gameDates.push(new Date(10,17,2020));
    
    //show all the dates in the array in sql format
    for(var date in gameDates)
        document.write(date.mysqlFormat()+"
");

Inheritance

Inheritance, since the inception of ES6(2015), has become significantly easier in JavaScript and much more similar to Java. ES6 inheritance uses the extends and super keywords to create subclasses that inherit data and functions from their parent classes. Here is an example of a DateTime class that acts as a child of the Date class written earlier in this lesson.
class DateTime extends Date{
    constructor(month=1, day=1, year=1970, hour=12, minute=0, second=0){
        super(month, day, year);
        this._hour=hour;
        this._minute=minute;
        this._second=second;
    }
    
    //GETTERS
    //write the getters for hour, minute, second
    
    //SETTERS
    //write the setters for hour, minute, second
    
    //OTHER METHODS
    toString(){
        return super.toString()+"  "+hour+":"+minute+":"+second;
    }
    //write other methods as needed (e.g. military time, etc)
}
Line (1) - the keyword extends creates the inheritance relationship
Line (3) - the super method calls the constructor of the parent class
Line (17) - the call to super.toString executes the toString method from the parent class

External Classes

For organization/reusability purposes, it is best to store your objects in their own .js files and import them into programs as needed. Also, note that any objects created on a page are only valid while that page is loaded. If you desire to use created objects on another page, you would need to send them through a server in some manner.
<script src='Date.js'></script>
<script>
    var today=new Date(12,25,2020); 
</script>
In the example above, all of the code for the Date class, previously written in this lecture is saved in the file Date.js. This file can then be included in any page that want to use the class.