OOPS расшифровывается как система объектно-ориентированного программирования. Это парадигма программирования, которая делает упор на использование объектов и классов для представления в коде сущностей и концепций реального мира.

В ООП класс — это план или шаблон для создания объектов, а объект — это экземпляр класса. Каждый объект имеет свой собственный набор атрибутов (свойств) и поведения (методов), которые определяются его классом.

OOPS обеспечивает несколько преимуществ, включая повторное использование кода, модульность и инкапсуляцию. Это позволяет разработчикам писать более эффективный и организованный код, упрощая его обслуживание и расширение с течением времени.

Некоторые популярные языки программирования, поддерживающие OOPS, включают Java, C++, Python, Ruby и JavaScript.

В OOPS есть четыре столпа, которые перечислены ниже. Эти концепции направлены на реализацию реальных сущностей в программах.

  • Наследование
  • Инкапсуляция
  • Абстракция
  • Полиморфизм

Наследование

Наследование — это фундаментальная концепция объектно-ориентированного программирования (ООП), которая позволяет одному классу наследовать свойства и поведение другого класса. Это означает, что новый класс может быть создан путем расширения существующего класса, и новый класс будет иметь доступ ко всем общедоступным и защищенным членам родительского класса.

Вот пример наследования в Java:

public class Animal {
    protected String name;
    protected int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println(name + " is eating.");
    }

    public void sleep() {
        System.out.println(name + " is sleeping.");
    }
}

public class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }

    public void bark() {
        System.out.println(name + " is barking.");
    }
}

В этом примере мы определили родительский класс Animal с двумя переменными-членами name и age и двумя методами eat() и sleep(). Затем мы определили дочерний класс Dog, который расширяет класс Animal.

Класс Dog наследует переменные-члены name и age, а также методы eat() и sleep() класса Animal. Он также определяет новый метод bark(), специфичный для собак.

В этом примере мы создали новый объект Dog с именем Buddy и возрастом 3 года. Когда мы вызываем методы eat() и sleep() для объекта dog, Java будет использовать реализации из класса Animal. Когда мы вызываем метод bark() для объекта собаки, Java будет использовать реализацию из класса Dog.

Используя наследование, мы можем повторно использовать код и избегать дублирования, а также создавать иерархию классов, моделирующую отношения между различными типами объектов. Это может привести к более чистому, удобному для сопровождения коду, который легче понять и модифицировать.

Инкапсуляция:

Инкапсуляция — это фундаментальная концепция объектно-ориентированного программирования (ООП), которая относится к практике объединения данных и методов внутри класса и ограничению доступа к ним извне класса. Это достигается путем определения членов класса как закрытых и предоставления общедоступных методов получения и установки для доступа и изменения данных.

Вот пример инкапсуляции в Java:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

В этом примере мы определили класс Person с двумя закрытыми переменными-членами name и age. Эти переменные недоступны извне класса, что означает, что они не могут быть изменены или доступны напрямую.

Чтобы обеспечить контролируемый доступ к этим переменным, мы определили общедоступные методы получения и установки getName(), setName(), getAge() и setAge(), которые позволяют нам читать и изменять данные контролируемым образом.

Например, чтобы создать новый объект Person и задать его имя и возраст, мы можем сделать следующее:

Person person = new Person();
person.setName("John");
person.setAge(25);

И чтобы получить имя и возраст человека, мы можем использовать следующее:

String name = person.getName();
int age = person.getAge();

Инкапсулируя данные и методы в классе Person, мы добились того, что внутренние детали класса скрыты от внешнего мира и доступны только через общедоступный интерфейс, предоставляемый классом. Это дает несколько преимуществ, включая улучшенную целостность данных, лучшую организацию кода и более простое обслуживание и отладку.

Абстракция:

Абстракция — это фундаментальная концепция объектно-ориентированного программирования (ООП), которая относится к практике сокрытия сложных деталей реализации системы за более простым и абстрактным интерфейсом. Это достигается за счет определения абстрактных классов и интерфейсов, которые обеспечивают общий обзор системы, не раскрывая лежащих в основе деталей реализации.

Вот пример абстракции в Java:

public interface Animal {
    void makeSound();
}

public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

В этом примере мы определили интерфейс Animal с одним абстрактным методом makeSound(). Этот метод обеспечивает высокоуровневую абстракцию того, что делает животное, без указания деталей того, как оно это делает.

Затем мы определили два класса Dog и Cat, которые реализуют интерфейс Animal. Эти классы предоставляют конкретные реализации метода makeSound() для собак и кошек соответственно, что скрывает основные детали того, как они издают звуки.

Animal animal1 = new Dog();
Animal animal2 = new Cat();

animal1.makeSound(); // prints "Woof!"
animal2.makeSound(); // prints "Meow!"

В этом примере мы создали два объекта интерфейса Animal, но присвоили их переменной Dog и Cat соответственно. Когда мы вызываем метод makeSound() для каждого объекта, Java автоматически вызывает правильную версию метода на основе фактического типа объекта во время выполнения. Это пример динамического полиморфизма и абстракции, когда поведение программы определяется во время выполнения на основе фактического типа объекта, а основные детали реализации скрыты за высокоуровневой абстракцией.

Полиморфизм:

Полиморфизм — это концепция объектно-ориентированного программирования (ООП), которая позволяет обрабатывать объекты разных классов так, как если бы они были одного и того же класса. Это означает, что один и тот же метод может использоваться для обработки объектов разных типов без необходимости знать их точные типы во время компиляции.

В Java полиморфизм может быть достигнут за счет перегрузки и переопределения методов.

Пример перегрузки метода:

Перегрузка методов позволяет нескольким методам иметь одно и то же имя, но с разными параметрами. Вот пример:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }
}

два метода с одинаковым именем add, но с разными типами параметров (int и double). Это означает, что мы можем использовать метод add для добавления двух целых чисел или двух чисел типа double, и Java автоматически выберет правильную версию метода на основе типов параметров.

Пример переопределения метода:

Переопределение метода — это когда подкласс предоставляет конкретную реализацию метода, который уже предоставлен его родительским классом. Вот пример:

public class Animal {
    public void makeSound() {
        System.out.println("Animal is making a sound");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

В приведенном выше примере у нас есть родительский класс Animal с методом makeSound(). Затем мы создали два подкласса Cat и Dog, оба из которых переопределяют метод makeSound() своей собственной реализацией.

Animal animal1 = new Cat();
Animal animal2 = new Dog();

animal1.makeSound(); // prints "Meow!"
animal2.makeSound(); // prints "Woof!"

В этом примере мы создали два объекта класса Animal, но присвоили их переменной Cat и Dog соответственно. Когда мы вызываем метод makeSound() для каждого объекта, Java автоматически вызывает правильную версию метода на основе фактического типа объекта во время выполнения. Это пример динамического полиморфизма, когда поведение программы определяется во время выполнения на основе фактического типа объекта.