What Is Object Oriented Programming?

Adam Turner
The Startup
Published in
16 min readOct 17, 2020

FClassical Definition of OOP

Object Oriented Programming (OOP) is a programming paradigm which tries to emulate real world problems using the abstract concept of ‘objects’ as a data structure which can be mutated and referenced.

There is no dictionary definition of the phrase OOP, but we can refer to Wikipedia’s summary to glean a semi-‘official’ account of its use:

Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code: data in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods).https://en.wikipedia.org/wiki/Object-oriented_programming

My Background in OOP

I have personally been programming for around 4 years as a hobbyist, student and professional developer. Academically, I hold a short-course certification in Object Oriented Programming with Java from City University, London amongst other various courses I have studied and books I have read.

The above does not make me an authority on this subject; but I feel I can certainly help those searching for an initial understanding and conceptual brief of OOP.

It’s imagined that if you are reading this article and have found it through search, you don’t yet have a mental concept of OOP nor have implemented it in practice. Let me assist you there.

How can learning OOP benefit me?

It is certainly a concept that is extremely useful for budding developers and programmers to understand, as approaching software or web development projects using OOP (as opposed to procedural approaches), cuts development time, reduces repetition and leads to an easier to produce, maintain and understand, codebase.

Not only that, but pretty much every professional developer uses objects and classes as part of their data structures.

If you don’t understand objects and the basic principles of OOP, you won’t survive very long as a professional developer, or at least you will be limited in your scope for producing more complex applications than perhaps a static simple program that computes values.

To get you to a better understanding of OOP, I will use code examples using the highly popular JavaScript ES6 language as reference to highlight concepts discussed.

I have deliberately omitted from this article, all aspects of OOP, as I feel it is important only to understand a few major concepts, before diving deeper. In this way, I’ve abstracted OOP for the beginner in a way that can be understood with perhaps a little programming background.

Approaching Programming Problems: Procedural versus OOP

To better understand OOP, you must understand programming in its infancy, before the creators of our modern languages modified popular high level programming languages to use objects to overcome the difficulties of time consuming, procedural — line by line — programming approaches.

Infancy of Computing — Pre OOP

Very simple definitions of programming often refer to giving the computer an algorithm, which we understand as a simple set of logical instructions that lead to a set outcome. A common metaphor used might be of baking a cake.

We can understand in the English language that to “bake a cake” is an abstraction of a more refined process, which we can further break down into simple instructions. E.G 1. Add flour. 2. Mix and Beat Eggs…etc etc

https://slideplayer.com/slide/9745062/

Computers, at their heart, are ‘simple’ machines in this respect, that can compute or process instructions at lightening speed, depending on various factors. We can give the computer these instructions procedurally — one after another, with intention that they are executed consecutively and iteratively.

Instructions at their rawest form are binary — they are read at a low level as a series of 1s and 0s e.g 10010100, interpreted via electrical signals that are on or off, high or low or even for example in the change in dimples on the surface of a CD or DVD.

Humans can’t instruct computers to do what they want (or program them) in this form due to the sheer volume of bits required to communicate simple instructions.

It just isn’t practical to write binary or machine level code these days, although it was certainly attempted by historical computer scientists — such as Ada Lovelace and Charles Babbage. They produced programs that solved basic mathematical computations; but the machines they used and the tools available at the time (often using punch cards) were very limited in their processing power and ability to execute these binary instructions.

As a result, those that developed modern computing, abstracted the low level instructions to a higher level language — one that humans can interpret and understand quickly, with a little knowledge and training.

The following is a simple snippet of a procedural code base that produces the square of a number.

let squareOf2 = 2 * 2;

This is fairly useful for its given case, which was to find the square of 2 and store it within a mutable variable called ‘squareOf2’.

However, writing code like this is fairly useless if we want to compute given cases in the future without re-writing a statement for each case.

For example, to square all the numbers from 1 to 10, you’d have to write something like this…

let squareOf1 = 1 * 1;
let squareOf2 = 2 * 2;
let squareOf3 = 3 * 3;
...

Functional Programming

The previous example highlighted the caveat of a procedural approach to programming. To achieve outcomes, solve problems or implement algorithms, we’d have to write the same thing over and over again top to bottom.

We’d repeat ourselves throughout the program and our final product will be one very long code file which would be hard to maintain.

To overcome these obstacles, developers of modern ‘high level’ programming languages (understood as — abstracting or summarising lower level instructions to more succinct operations) produced a functional programming approach, which allowed the developer the flexibility of encapsulating or ‘capturing’ their what would otherwise be repetitive coding behaviours, into easy to reference functions, that could be named and reused.

That is, rather than re-inventing the wheel every-time, as in the prior example, programmers can now simply call a function they write once and change the input argument (data) as they see fit.

Take the following example of a ES6 arrow-notation function below, that encapsulates the above process and solves the algorithmic challenge of squaring a given number (an argument) multiple times:

const square = (base) => {
return base * base;
};

If you don’t know JavaScript all that well; to highlight the above notation bit by bit, I have simply assigned to a constant (in most cases, immutable variable) called square, a function which takes ‘base’ (a parameter) which can be anything the user chooses to pass in; and then run a simple calculation on it to square whatever number the user passes in.

Therefore, the outcome of this functional process to square all the numbers from 1 to 10 could be achieved by re-using the above code in the following form (yes, it’s also not ideal — we’ll get to that!).

square(1) // Produces 1
square(2) // Produces 4
square(3) // Produces 9
square(4) // Produces 16
square(5) // Produces 25
...

We can further make this process even simpler for a future use case.

What if we had to square not 10, but 100 or 1000 or more numbers in a go?

Even with the function above, this would still take a little bit of repetitive writing to achieve.

To solve this problem, we could implement a flexible algorithm into a function which allows the user to pass in a single integer as an argument that determines the number of square numbers to compute and when called, executes that calculation as many times as specified.

As below, here is my example of a function that would achieve such an outcome using a conditional operator (a while loop):

// This function squares all numbers consecutively from 1 to and inclusive of the passed in limit e.g. 1 to 10const square = (limit) => {
x = 1;
while(x <= limit) {
return(x * x);
x++;
}
}
square(10); // Output is below1
4
9
16...
100

See the difference in a functional approach?

We are moving away from the procedural — statement by statement programming, to a more modular, repeatable and encapsulated form.

The end result is that we can write functions that solve specific, broken down algorithms, or parts of yet an even larger algorithm, and use these throughout the program with much more ease than repeating or re-inventing the wheel on each occasion. This also reduces the scope for human typing errors.

That’s great, but what about Object Oriented Programming — you haven’t got to the point yet? What is an Object?

So we understand now, having read the previous summaries, that a functional approach to programming leads to less repetition and abstraction of real world problems into a form of language that we can reuse and refer to throughout the program.

I turned the repetitive process of ‘squaring’ any number into something I could reference in the future simply using the word square().

I no longer had to re-write everything that was encapsulated within that square function, every time I wanted to square a set of numbers.

Objects are yet another form of data structure within many programming languages, often referred to as Object Oriented languages. I use JavaScript throughout this article — but perhaps the best known example of an OOP is the Java language (which has some similarities to JavaScript, but is certainly not a parent or predecessor / relative of it).

If you’ve been programming a little in the past but don’t yet understand Objects or OOP, you might understand simple data structures at this stage.

Objects are a data structure that model real world ‘objects’. They behave like a little more advanced version of an array — but are extremely flexible and easily manipulated.

You may know and have very likely encountered variables (one simple and fundamental way to play with data).

Variables reference a location in memory within the computer and can either be immutable or mutable — that is they can be static / unchangeable or changeable, which we reference in the JavaScript ES6 notation as either let, var or const.

The following code uses mutable variables (using the let keyword to denote a variable is being declared) to hold data:

let variableOne = 1;
let name = 'Adam Turner';

This is great — we can assign bits of primitive data, such as strings of text, numbers or boolean values to a space in memory which we can later reference or manipulate.

variableOne += 2;
console.log(variableOne);
// Prints 3

You may be aware of arrays, for example, checkout the following ‘array’ (or in English — consecutive grouping of things stored in memory) and understand that it is just yet another way we structure data:

let arrayOfColours = ['Red', 'Orange', 'Pink', 'Blue'];

This is useful, as we can store information in this human understandable form, iterate over it in various ways or manipulate it.

It represents a kind of logical list of things we want to store, rather than a variable, which is just a singular value (not a list of values).

I understand variables, arrays and so on, but what is an object?

Objects take the idea of data structures one step further with the goal of giving the programmer flexibility in modelling within them, real world objects I.E things we encounter within the world outside of computers, such cars, tables, music albums etc.

Pretty much anything you can dream up of, could be in someway represented computationally as an object.

https://medium.com/@cscalfani/goodbye-object-oriented-programming-a59cda4c0e53

As long as the real world ‘object’ we are trying to capture or abstract into the computer has some form of logic to it (i.e. we cannot model a jumbled set of nothing), we can turn it into a very flexible data structure, called an object.

The following is an example of how to declare a mutable object ‘literal’ in JavaScript ES6:

let car = {};

It is that simple to declare an object, but what sets objects apart from other primitive data structures?

Objects have the following attributes to them in their most basic form:

  1. PROPERTIES : these are typically expressed as key value pairs which look like the following ‘key : value’, where the key is the property, and the value is the value. When we write the properties of an object (for example as above we chose a ‘car’ object) we want to try and capture the relevant properties and their values specific to that object. This might mean, with a car, a key of ‘age’ and a value denoting the date the car was manufactured (x or in the following example 10).
  2. BEHAVIOUR: I have used this term, instead of methods or other references the object can ‘do’, because there are more behaviours than just methods. To break down behaviour we can define within an object the following possible behaviours:
    - Method / Function: This could be a simple function which returns a value, for example, a method called ‘recommended sale date’ could take the age value (defined in the properties above) and add 10 to it, returning the year that one should sell the car by.
    - Getters / Setter: These are specific behaviours that get for the user / programmer, values from the property / value pairs within the object or change (mutate) those values.

Let’s take a look at an object in practice using JavaScript again:

let volvo = {
model: 'Volvo 2',
age: 10,
findSaleDate() {
return age + 10;
},
get age() {return age};
}console.log(volvo.age) // displays 10
console.log(volvo.findSaleDate()); // displays 20
console.log(volvo[model]); // displays 'Volvo 2'

The above is great for a single use case of a ‘Volvo 2' car.

As above, we defined the volvo object, gave it some properties (model, age) and behaviour (a method called findSaleDate() that when called returns the age of the volvo plus 10.

This would be helpful in a program specific to volvo cars only.

However, what if we wanted to go a step further and really implement objects for a large code base with the aim of reducing repetition and abstracting these real world objects to reusable, modular entities?

Objects Summarised

As above, you have seen that objects are just another data structure, which we can manipulate and are a little more flexible than variables and arrays, for example, as the programmer can define the properties of the object as they wish and subsequently, how it behaves.

You saw that we defined an object literal in a similar way to how we define a variable, but using {} after the equality operator.

We then enclosed within that block, properties and behaviour in the form of key value pairs for the properties, and what are very similar to functions, as the methods, getters, setters, which make up the overall ‘behaviour’ or ‘doing’ capabilities of the object.

I have omitted from this article, the subtleties of privacy that many programmers implement in objects, for example, by denoting properties the programmer does NOT want to be changed directly as beginning the key with an underscore. E.G _name : volvo.

To understand how to build objects properly within JavaScript or your given object oriented language, you really need to understand data structures and then work on the syntax for objects, which is out of the scope of this article, that has been written with aim at developing a beginner’s understanding of OOP on a high level.

Going One Step Further — Objects and Classes

In this final and advanced stage of understanding OOP on a high level, you have so far encountered objects as a data structure which allows the programmer a great deal of flexibility in defining the objects makeup and behaviour.

Classes act as a blueprint for building objects. We could think carefully about the prior scenario, and create a blueprint for building cars (a Car class) which itself produces car objects, which can be defined by the developer or user.

There could also be sub-classes to the car class, for example, a convertible class, or a sports class or whatever is required for the use case of the program.

This is where inheritance comes into play.

There are several main concepts to OOP which I will summarise at the end of this article, but of the most important (bar encapsulation — which you will have understood in the functional programming explanations) is perhaps inheritance.

Inheritance — Parent and Child Classes

As in nature, or simple biology, children inherit features of their parents, within the animal and plant kingdoms. This rings true with the programming paradigm of OOP too.

Let us structure a ‘car factory’ program which has a very high level purpose of producing different cars of different types including sports cars, convertibles and 4x4 jeeps.

We could create a super (parent) class which holds all of the common features (attributes or behaviour) of the objects it is supposed to be a blueprint for.

We could then write further sub or child classes, which inherit from this parent class, those common features, but have specific or custom features that relate only to that child class also. In plain English, we could refer to this child classes as ‘custom classes’ (although this terminology is not used professionally) — as they customise further the blueprint denoted by the parent.

Child classes inherit all of the properties and behaviour of their parent class — in programming lingo, they ‘extend’ the superclass.

These properties and behaviours do not need to be re-written in majority case.

Take the following example of a parent class to catch all cars features where possible (ignore the constructor for now):

class Car {
// PROPERTIES
constructor(model, colour) {
model = model; age = 0; colour = colour; }
// BEHAVIOUR
printCarSummary() {
return `Model: ${model}. Colour: ${colour}. Age: ${age}`
}
}

The above defines a ‘Car’ class, which has a constructor (a method that initialises or ‘constructs’ the object).

The constructor defines that, that particular object which is being constructed will have a model property that holds the specific value passed in the parenthesis (model, colour). The same action is taken for colour.

Then under behaviour, there is a printCarSummary() method, which simply returns a string summarising the values of the object (model, colour and age).

We can produce a ‘new’ object instance of Car using the Car class as a blueprint utilising the following syntax.

We can then access that object’s specifically defined state and behaviours however we wish.

let myRedVolvo = new Car('Volvo', 'Red');console.log(myRedVolvo.colour); // Displays redconsole.log(myRedVolvo.printCarSummary()); // Prints "Model: Volvo. Colour: Red. Age: 0"

The prior parent ‘Car’ object isn’t useful for specific use cases — what if we wanted to quickly define convertibles and jeeps?

Let’s just use a convertible as an example and define a convertible class that inherits all of the car classes properties and behaviour, but has own properties that are unique to that convertible class, such as ‘isHardTop’ — a boolean value denoting whether the convertible is a hard top or not.

class Convertible extends Car {
constructor(model, isHardTop, colour) {
super(model, colour);
_isHardTop = isHardTop;
} fastCarNoise() { return 'Zooooom!';
}
}

Now we have a child Convertible class, which inherits from its parent Car class, all of those features, but adds or extends its own features within the new class.

For example, we don’t have to re-write the printCarSummary() method because it is inherited from the parent Car class AND we can now access the fastCarNoise(), which is specific to the Convertible class.

let bugatti = new Convertible('Bugatti Veyron', true, 'Blue');
console.log(bugatti.fastCarNoise()); // Prints 'Zooooom!'
console.log(bugatti.model); // prints 'Bugatti Veyron'

You can see now that it is much easier to encapsulate general or common attributes of objects in parent classes, and then where there is a specific use case, create child classes that can be used to create even more granular objects.

I have deliberately omitted certain programming practises in ES6 for sake of brevity, for example, explaining how the .this method works. Please if you are interested and want to learn how to implement OOP in your JavaScript programs, I would recommend studying a formal course on the subject.

Summary — What is Object Oriented Programming?

OOP is a way of thinking and a form of tools within programming that implements syntax enabling us to go beyond the old style procedural programming paradigm of trying to solve problems iteratively top to bottom in a slow and logical fashion that ultimately leads to repetition and time consumption.

We can think of objects now in a multidimensional fashion, as another data structure, which is highly flexible, reusable and great for abstracting a problem in a way humans can more easily understand.

Objects are summarised as having properties and behaviour.

Seeing a program, for example, a car factory system, as one which denotes classes (blueprints for objects) in a parent > child fashion — allows us to be very modular in how we produce objects for later manipulation or access.

In totality, objects allow us to understand programming in a more real world fashion, beyond top to bottom instructions for a simple machine, pushing conceptually closer to human ways of processing information i.e. understanding the world in programs as physical objects that have a state (properties and values) and do things or act. OOP in short, makes life a lot easier.

Further Reading — OOP All Concepts

I have only included in this article the main concepts I think you need to understand for you to achieve at least a first grip of OOP on a high level.

I strongly recommend, however, that you explore and read about all of the concepts within OOP to get a deeper understanding.

I discussed abstraction, in the form of looking at how we take a complex task and ‘abstract’ or reduce it to a smaller or more modular task when writing functions.

Encapsulation could also be understood throughout this article in some form through looking at how certain features of objects (or even functions) could be ‘captured’ or ‘encapsulated’ within their own environments.

The major topic of inheritance was discussed using examples of parent (super) classes and sub or child classes.

The following graphical representation highlights the major components of OOP in the Java programming language, which may be relevant depending on your use case:

https://www.geeksforgeeks.org/object-oriented-programming-oops-concept-in-java/

Key Concepts Discussed in this Article
1. Procedural versus Object Oriented Programming
— OOP enables greater flexibility and is closer to producing real world implementations of real world problems, than the simple algorithm implementations we first looked at in the form of baking a cake, following instructions top to bottom.
2. Functional Programming — this is a modern approach to writing programs, in the form of using functions (modular bits of code that we can re-use). OOP takes this concept and advances it.
3. Objects are another data structure — at their rawest form, objects are an advanced data structure which allows the programmer the ability to define properties and behaviour of those objects.
4. Classes — are blueprints for making objects, they are used to specify the makeup of objects. Super (or parent) classes pass all features down to further sub-classes or child classes, which themselves can have specific features. We use the classes to make new objects, typically using the ‘new’ keyword.

I hope you found this article useful. Please feel free to reach out to me directly if you notice any major discrepancies or you feel there is an error somewhere.

To find out more about me, feel free to follow me on Twitter:

Happy Coding!

https://twitter.com/csturner88

--

--

Adam Turner
The Startup

Frontend Developer. JavaScript & TypeScript Padawan. Based in South West London. Portfolio: adamrichardturner.dev