Principles of object-oriented programming

Published in the Java Developer group
Hi! Have you ever wondered why Java is designed exactly as it is? I mean, you declare classes and create objects based on classes, classes have methods, etc. But why is the language structured so that programs consist of classes and objects, and not something else? Why was the concept of an "object" invented and put at the forefront? Are all languages designed this way? If not, what advantages does it give to Java? As you can see, there are a lot of questions :) Let's try to answer each of them in today's lesson. Principles of object-oriented programming - 1

What is object-oriented programming (OOP)?

Of course, Java isn't made up of objects and classes just for fun. They aren't a whim of Java's creators, and not even their invention. There are many other languages based on objects. The first such language was called Simula. It was invented back in the 1960s in Norway. What's more, the concepts of a "class" and "method" appeared in Simula. By the standards of software development, Simula seems like an ancient language, but anyone can see its "family resemblance" with Java. You can probably easily read the code written in this language and explain in broad strokes what it does :)
	Class Rectangle (Width, Height); Real Width, Height;

	    Real Area, Perimeter;

	    Procedure Update;
	      Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
	      Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
	    End of Update;

	    OutText("Rectangle created: "); OutFix(Width,2,6);
	    OutFix(Height,2,6); OutImage;
	 End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;

	    OutText("ColouredRectangle created, color = "); OutText(Color);
        End of ColouredRectangle;

      	 Ref(Rectangle) Cr;
	 Cr :- New ColouredRectangle(10, 20, "Green");
This code sample code was taken from "Simula - 50 years of OOP" by Weekly-geekly. As you can see, Java isn't so very different from its grandfather :) This is due to the fact that the appearance of Simula marked the birth of a new concept: object-oriented programming. Wikipedia defines OOP like this: "Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data, in the form of fields (often known as attributes), and code, in the form of procedures (often known as methods)." In my opinion, this is a really good definition. It wasn't long ago that you began to learn Java, but this definition probably doesn't contain any words you don't know :) Today OOP is the most common programming methodology. In addition to Java, OOP principles are used in many popular languages that you may have heard about. For example, C++ (actively used in game development), Objective-C and Swift (used to write programs for Apple devices), Python (most popular in machine learning), PHP (one of the most popular web development languages), JavaScript (it's easier to say what it isn't used for) and many others. So, what is are the principles of OOP anyway? We'll tell you in detail.

OOP Principles

These are the foundation of the foundation. The 4 main features that together form the object-oriented programming paradigm. Understanding them is essential to becoming a successful programmer.

Principle 1. Inheritance

Good news: you already know some of the principles of OOP! :) We've already encountered inheritance a couple of times in lessons, and we managed to use it. Inheritance is a mechanism that lets you describe a new class based on an existing (parent) class. In doing so, the new class borrows the properties and functionality of the parent class. What is inheritance for and what advantages does it provide? Above all, code reuse. The fields and methods declared in parent classes can be used in descendant classes. If all types of cars have 10 common fields and 5 identical methods, you just need to move them into the Auto parent class. You can use them in descendant classes without any problems. Solid advantages: both quantitative (less code) and, as a result, qualitative (classes become much simpler). Moreover, inheritance is very flexible — you can add write separate functionality that the descendants are missing (some fields or behavior that are specific to a particular class). In general, as in real life, we all are somewhat similar to our parents, but also somehow different from them :)

Principle 2. Abstraction

This is a very simple principle. Abstraction means to identify the main, most significant characteristics of something, while simultaneously discarding anything minor and insignificant. No need to reinvent the wheel. Let's recall an example from an old lesson about classes. Suppose we're creating a filing system for company employees. To create "employee" objects, we've written an Employee class. What characteristics are important to describe them in the company filing system? Name, date of birth, SSN, and employee ID. But it's unlikely we'll need the employee's height, eye color, or hair color for this type of record. The company has no need for such information about an employee. So, in the Employee class, we declare the following variables: String name, int age, int socialSecurityNumber, and int employeeId. And we abstract away unnecessary information like eye color. However, if we're making a filing system for a modeling agency, the situation changes dramatically. A model's height, eye color, and hair color are important characteristics, but her SSN is absolutely irrelevant to us. So, in the Model class, we create the following variables: String height, String hair, String eyes.

Principle 3. Encapsulation

We've already run into this. In Java, encapsulation means restricting the ability to read and change data. As you can see, the term is based on the word "capsule". We'll use a "capsule" to hide some important data that we don't want others to change. Here's a simple example from real life. You have a first name and a last name. All your friends know them. But they don't have the ability to change your first or last name. We might say that the process to do that is "encapsulated" by the court system: you can change your last name only through the court clerk, and only you can do it. Other "users" have "read-only" access to your first and last name :) Another illustrative example is cash kept at home. Leaving it in plain sight in the middle of your room is not a good idea. Any "user" (person who comes to your house) will be able to change the amount of your money, i.e. they can take your money. It would be better to encapsulate it in a safe. Then access would be available only to you and only by using a special code. Obvious examples of encapsulation that you've already worked with are access modifiers (private, public, etc.), as well as setters and getters. If you don't encapsulate the Cat class's age field, then anyone can write:
Cat.age = -1000;
The encapsulation mechanism lets us protect the age field with a setter method, where we can ensure that age cannot be set to a negative number.

Principle 4. Polymorphism

Polymorphism is the ability to work with several types as if they were the same type. Moreover, the objects' behavior will be different depending on their type. Does that sound complicated? Let's make sense of it right now. Take the simplest example: animals. Create an Animal class with a single speak() method, and two subclasses — Cat and Dog.
public class Animal {

   public void speak() {


public class Dog extends Animal {

   public void speak() {
       System.out.println ("Woof-woof!");

public class Cat extends Animal {

   public void speak() {
Now we'll try to declare an Animal reference variable and assign a Dog object to it.
public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
What method do you think will be called? Animal.speak() or Dog.speak()? The method in the Dog class will be called: Woof-woof! We created an Animal reference, but the object behaves like a Dog. If necessary, it could behave like a cat, horse, or some other animal. The important thing is to assign a specific subclass to the general Animal reference variable. This makes sense, because all dogs are animals. That's what we had in mind when we said "the objects' behavior will be different depending on their type." If we created a Cat object...
public static void main(String[] args) {

   Animal cat = new Cat();
the speak() method would display "Meow!" But what do we mean by 'the ability to work with several types as if they were the same type'? This is also pretty straightforward. Let's imagine that we're creating a barbershop for animals. Our barbershop should be able to give any animal a trim, so we create a trim() method with an Animal parameter (the animal getting a haircut).
public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!");
And now we can pass Cat and Dog objects to the trim() method!
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

And here's the clear example: the AnimalBarbershop class works with the Cat and Dog types as if they were the same type. At the same time, Cat and Dog have different behaviors: they each speak differently.

Why do we need OOP?

Why did OOP ever even arise as a new programming concept? Programmers had functioning tools, such as procedural languages. What prompted them to invent something fundamentally new? Above all, the complexity of the tasks that they faced. If 60 years ago the programmer's task was something like "evaluate some mathematical expression", now it could be something like "implement 7 different endings for the game S.T.A.L.K.E.R., depending on combinations of the player's decisions made at points A, B, C, D E, and F in the game." As you can see, the tasks have obviously become more complicated over the past decades. And as a result, the data types have become more complicated. This is another reason why OOP appeared. A mathematical expression can be evaluated easily using ordinary primitives. No objects are needed here. But the task with the game endings would be difficult to even describe without using custom classes. That said, it is quite easy to describe it using classes and objects. Obviously, we'll need several classes: Game, Stalker, Ending, PlayerDecision, GameEvent, and so on. In other words, even without starting to solve the problem, we can easily "sketch out" a solution in our head. The increasing complexity of the tasks forced programmers to divide them into parts. But this wasn't so easy to do in procedural programming. And quite often a program was like a tree with lots of branches representing all the possible execution paths. Depending on certain conditions, one branch of the program or another was executed. For small programs, this was convenient, but it was very difficult to divide a large problem into parts. This was yet another reason for the emergence of OOP. This paradigm gave programmers the ability to divide a program into a bunch of "modules" (classes), each of which does its own part of the work. By interacting with each other, all the objects accomplish the work of our program. In addition, we can reuse our code elsewhere in the program, which also saves a lot of time.
Comments (19)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
Aldo Luna Bueno
Level 28 , Peru
22 February, 00:36
¿Por qué necesitamos POO? Porque sirve para hacerle frente a muchos de los problemas cada vez más complejos de la actualidad gracias a tres grandes características: 1. se hace más fácil para la mente humana describir estos problemas en términos de clases y objetos, 2. permite dividir el programa en módulos manejables y 3. permite reutilizar el código, una clara ventaja en programas grandes.
Level 19 , Poland, Poland
22 November 2021, 19:36
Someone could explain the difference between
Animal dog = new Dog();
Dog dog = new Dog();
Anonymous #10853261
Level 21 , United States
11 December 2021, 18:23
It has to do with the narrowing and widening of objects from type casting. In this particular example, it is showing that a Dog() object can be held as either an Animal or Dog reference. However, in either case, the object will inherit the methods from the Dog class. Since the dog object is contained in the Animal reference, it is still a Dog() class meaning dog.speak() returns 'Woof-woof!'. I probably did a piss-poor job of explaining this, so have a look here for a better explanation under 5.) Type Casting. I hope this helps!
Jonaskinny Java Developer at Sandmedia
22 February, 21:41
It has to do with variable hiding. Sort of like ignoring polymorphism where attributes are common.
public class Poly {

    public static class Animal {
        int x = 1;
        int y = 2;
        public int getX() {return x;}
        public int getY() {return y;}
    public static class Dog extends Animal {
        int x = 9;
        int z = 3;
    public static void main(String[] args) {
        Animal a = new Animal();
        Animal b = new Dog();
        Dog c = new Dog();
        // Dog d = new Animal(); wont compile cuz not all Animals are dogs

        o(a.x + " " + a.y);
        o(b.x + " " + b.y);
        // o(b.x + " " + b.y + " " + b.z); wont compile cuz only Dogs have z's
        o(c.x + " " + c.y + " " + c.z); // a Dog declared as a Dog can see z
        o(a.getX() + " " + a.getY());
        o(b.getX() + " " + b.getY());
        o(c.getX() + " " + c.getY());

    static void o(Object o) {
outputs: 1 2 <-- animal so show me animal 1 2 <-- dog declared as animal so where common show me animal 9 2 3 <-- dog declared as dog so where common show me dog 1 2 <-- animal accessed via methods instead of direct member access 1 2 <-- dog declared as animal accessed via methods instead of direct member access 1 2 <-- dog declared as dog accessed via methods instead of direct member access
Nathan G
Level 41 , Ontario, Canada
30 April 2021, 21:49
S.T.A.L.K.E.R games are great. My favorite is Call of Pripyat. :)
Dan Ursu
Level 27 , United Kingdom
6 April 2021, 12:21
What is the difference between creating a dog object in the following way?
Animal dog = new Dog();
And in this other way
Dog dog = new Dog();
Roman Grygorczuk
Level 19 , Cracow, Poland
1 November 2020, 19:33
I have a question regarding public void trim(Animal animal), actually Animal animal, how can I call it? passing class as a method parameter? Can you please share any article about this as this is very confusing for me. Thanks in advance!
Mecs Backend Developer
12 November 2020, 17:24
Actually trim() method receives an animal object as a parameter. So you need to pass an instance of Animal when you call it. In Java reference types can also be passed to methods in addition to primitive types.
// Various types of animal objects are created here
Cat cat = new Cat();
Horse horse = new Horse();
// trim() method is called with passing the above objects to it as an argument
Hope it's more understandable.
Ashish RajAnand
Level 13 , Bhilai , India
6 May 2020, 03:27
great but I can't get polymorphism can any one explain for me
Ashish RajAnand
Level 13 , Bhilai , India
6 May 2020, 03:41
I got it
Reymart Santiago
Level 12 , Makati, Philippines
25 April 2020, 14:01
Great article
Level 29 , Kyiv, Ukraine
7 April 2020, 11:00
Thanks for STALKER)
Jakub Góźdź
Level 31 , Katowice, Poland
12 March 2020, 10:03
Q: “Whats the object-oriented way to become wealthy?” A: Inheritance
Thomas Sixberry
Level 16 , Rochester Hills, United States
7 February 2020, 15:36
I just opened a door and the space inside is beyond what the eye can see in all directions.