Unit 1: OOP Fundamentals
Unit 1: OOP Fundamentals
OOP languages are not necessarily restricted to the object-oriented programming paradigm. Some
languages, such as JavaScript, Python, and PHP, all allow for both procedural and object-oriented
programming styles.
A class is an abstract blueprint that creates more specific, concrete objects. Classes often represent
broad categories, like Car or Dog that share attributes. These classes define what attributes an
instance of this type will have, like color, but not the value of those attributes for a specific object.
Classes can also contain functions called methods that are available only to objects of that type.
These functions are defined within the class and perform some action helpful to that specific object
type.
For example, our Car class may have a repaint method that changes the color attribute of our car.
This function is only helpful to objects of type Car, so we declare it within the Car class, thus
making it a method.
Imagine running a dog-sitting camp with hundreds of pets where you keep track of the names, ages,
and days attended for each pet.
How would you design simple, reusable software to model the dogs?
With hundreds of dogs, it would be inefficient to write unique entries for each dog because you
would be writing a lot of redundant code. Below we see what that might look like with objects rufus
and fluffy.
var rufus = {
name: "Rufus",
birthday: "2/1/2017",
age: function() {
return Date.now() - this.birthday;
},
attendance: 0
}
Grouping related information together to form a class structure makes the code shorter and easier to
maintain.
In the dogsitting example, here’s how a programmer could think about organizing an OOP:
• Create a class for all dogs as a blueprint of information and behaviors (methods) that all
dogs will have, regardless of type. This is also known as the parent class.
• Create subclasses to represent different subcategories of dogs under the main blueprint.
These are also referred to as child classes.
• Add unique attributes and behaviors to the child classes to represent differences
• Create objects from the child class that represent dogs within that subgroup
Next, we’ll take a deeper look at each of the fundamental building blocks of an OOP program used
above.
Classes
Classes are essentially user-defined data types. Classes are where we create a blueprint for the
structure of methods and attributes. Individual objects are instantiated from this blueprint.
Classes contain fields for attributes and methods for behaviors. In our Dog class example, attributes
include name & birthday, while methods include bark() and updateAttendance().
Here’s a code snippet demonstrating how to program a Dog class using the JavaScript language.
class Dog {
constructor(name, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return Date.now() - this.birthday;
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
Objects
Objects are, unsurprisingly, a huge part of OOP! Objects are instances of a class created with
specific data. For example, in the code snippet below, Rufus is an instance of the Dog class.
Example:
class Dog {
constructor(name, birthday) {
this.name = name;
this.birthday = birthday;
}
calcAge() {
//calculate age using today's date and birthday
return Date.now() - this.birthday;
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
//instantiate a new object of the Dog class, and individual dog named Rufus
const rufus = new Dog("Rufus", "2/1/2017");
Attributes
Attributes are the information that is stored. Attributes are defined in the Class template. When
objects are instantiated, individual objects contain data stored in the Attributes field.
The state of an object is defined by the data in the object’s attributes fields. For example, a puppy
and a dog might be treated differently at a pet camp. The birthday could define the state of an object
and allow the software to handle dogs of different ages differently.
Methods
Methods represent behaviors. Methods perform actions; methods might return information about an
object or update an object’s data. The method’s code is defined in the class definition.
When individual objects are instantiated, these objects can call the methods defined in the class. In
the code snippet below, the bark method is defined in the Dog class, and the bark() method is called
on the Rufus object.
class Dog {
//Declare protected (private) fields
_attendance = 0;
constructor(name, birthday) {
this.namee = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
Methods often modify, update or delete data. Methods don’t have to update data though. For
example, the bark() method doesn’t update any data because barking doesn’t modify any of the
attributes of the Dog class: name or birthday.
The updateAttendance() method adds a day the Dog attended the pet-sitting camp. The attendance
attribute is important to keep track of for billing Owners at the end of the month.
Methods are how programmers promote reusability and keep functionality encapsulated inside an
object. This reusability is a great benefit when debugging. If there’s an error, there’s only one place
to find it and fix it instead of many.
The underscore in _attendance denotes that the variable is protected and shouldn’t be modified
directly. The updateAttendance() method changes _attendance.
• Inheritance: child classes inherit data and behaviors from the parent class
• Encapsulation: containing information in an object, exposing only selected information
• Abstraction: only exposing high-level public methods for accessing an object
• Polymorphism: many methods can do the same task
Inheritance
Inheritance allows classes to inherit features of other classes. Put another way, parent classes extend
attributes and behaviors to child classes. Inheritance supports reusability.
If basic attributes and behaviors are defined in a parent class, child classes can be created, extending
the functionality of the parent class and adding additional attributes and behaviors.
For example, herding dogs have the unique ability to herd animals. In other words, all herding dogs
are dogs, but not all dogs are herding dogs. We represent this difference by creating a child class
HerdingDog from the parent class Dog, and then adding the unique herd() behavior.
The benefits of inheritance are programs can create a generic parent class and then create more
specific child classes as needed. This simplifies programming because instead of recreating the
structure of the Dog class multiple times, child classes automatically gain access to functionalities
within their parent class.
In the following code snippet, child class HerdingDog inherits the method bark from the parent
class Dog, and the child class adds an additional method, herd().
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
herd() {
//additional method for HerdingDog child class
return console.log("Stay together!")
}
}
Another Example:
//Parent class Dog
class Dog{
//Declare protected (private) fields
_attendance = 0;
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
herd() {
//additional method for HerdingDog child class
return console.log("Stay together!")
}
}
Encapsulation
Encapsulation means containing all important information inside an object, and only exposing
selected information to the outside world. Attributes and behaviors are defined by code inside the
class template.
Then, when an object is instantiated from the class, the data and methods are encapsulated in that
object. Encapsulation hides the internal software code implementation inside a class and hides the
internal data of inside objects.
Private/ Internal interface: methods and properties accessible from other methods of the same class.
Public / External Interface: methods and properties accessible from outside the class.
Let’s use a car as a metaphor for encapsulation. The information the car shares with the outside
world, using blinkers to indicate turns, are public interfaces. In contrast, the engine is hidden under
the hood.
It’s a private, internal interface. When you’re driving a car down the road, other drivers require
information to make decisions, like whether you’re turning left or right. However, exposing
internal, private data like the engine temperature would confuse other drivers.
Encapsulation adds security. Attributes and methods can be set to private, so they can’t be accessed
outside the class. To get information about data in an object, public methods & properties are used
to access or update data.
Within classes, most programming languages have public, protected, and private sections. The
public section is the limited selection of methods accessible from the outside world or other classes
within the program. Protected is only accessible to child classes.
Private code can only be accessed from within that class. To go back to our dog/owner example,
encapsulation is ideal so owners can’t access private information about other people’s dogs.
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
This allows us to hide important information that should not be changed from phishing and the
more likely scenario of other developers mistakenly changing important data.
Encapsulation adds security to code and makes it easier to collaborate with external developers.
When you’re programming to share information with an external company, you wouldn’t want to
expose the classes’ templates or private data because your company owns that intellectual property.
Instead, developers create public methods that allow other developers to call methods on an object.
Ideally, these public methods come with documentation for external developers.
• Adds security: Only public methods and attributes are accessible from the outside
• Protects against common mistakes: Only public fields & methods are accessible, so
developers don’t accidentally change something dangerous
• Protects IP: Code is hidden in a class; only public methods are accessible by the outside
developers
• Supportable: Most code undergoes updates and improvements
• Hides complexity: No one can see what’s behind the object’s curtain!
Abstraction
Abstraction is an extension of encapsulation that uses classes and objects, which contain data and
code, to hide the internal details of a program from its users. This is done by creating a layer of
abstraction between the user and the more complex source code, which helps protect sensitive
information stored within the source code.
A driver uses the car’s steering wheel, accelerator, and brake pedals to control the vehicle. The
driver does not have to worry about how the engine works or what parts are used for each
movement. This is an abstraction – only the important aspects necessary for a driver to use the car
are visible.
Similarly, data abstraction allows developers to work with complex information without worrying
about its inner workings. In this way, it helps to improve code quality and readability.
Polymorphism
Polymorphism means designing objects to share behaviors. Using inheritance, objects can override
shared parent behaviors with specific child behaviors. Polymorphism allows the same method to
execute different behaviors in two ways: method overriding and method overloading.
Method Overriding
Runtime polymorphism uses method overriding. In method overriding, a child class can implement
differently than its parent class. In our dog example, we may want to give TrackingDog a specific
type of bark different than the generic dog class.
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
track() {
//additional method for TrackingDog child class
return console.log("Searching...")
}
bark() {
return console.log("Found it!");
}
Method Overloading
Compile Time polymorphism uses method overloading. Methods or functions may have the same
name but a different number of parameters passed into the method call. Different results may occur
depending on the number of parameters passed in.
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
updateAttendance(x) {
//adds multiple to the dog's attendance days at the petsitters
this._attendance = this._attendance + x;
}
}
Conclusion
Object-oriented programming requires thinking about the structure of the program and planning out
an object-oriented design before you start coding. OOP in computer programming focuses on how
to break up the requirements into simple, reusable classes that can be used to blueprint instances of
objects. Overall, implementing OOP allows for better data structures and reusability, saving time in
the long run.
The End