Многие из вас слышали о терминах ООП, полиморфизме и наследовании. Вы, вероятно, изучали эти термины в семестровом курсе колледжа или университета. Многие из вас усвоили эти концепции, многие в замешательстве, и многие сомневаются в себе, стоит ли им продолжать программирование или нет……

Не беспокойтесь, в этой статье мы рассмотрим концепции объектно-ориентированного программирования. Мы также рассмотрим темы, связанные с концепциями ООП. По ходу дела мы постараемся ответить на основные вопросы и термины, продолжайте читать.
Так что же такое объектно-ориентированное программирование, также известное как ООП? Объектно-ориентированное программирование — популярная парадигма программирования, используемая практически в каждом сложном приложении.
Вопрос 1: Итак, вот наш первый вопрос: что такое парадигма программирования?
Ответ: парадигма программирования — это набор методов программирования, в основном способ программирования или подхода к проектированию и разработке программного обеспечения для выполнения конкретных требований.
Парадигма программирования помогает писать чистый и организованный код, который является косвенным решением сложных проблем.
Вот некоторые из наиболее популярных Парадигмы программирования, отличные от объектно-ориентированного программирования:

  1. Функциональное программирование
  2. Императивное программирование
  3. Логическое программирование
  4. Параллельное программирование
  5. Программирование, управляемое событиями

Мы рассмотрим вышеуказанные парадигмы в какой-нибудь другой статье (комментируйте, если да). Что касается концепций ООП, давайте углубимся в них.
Объектно-ориентированное программирование основано на четырех простых концепциях:

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

Давайте подробно изучим каждый из них и поймем их использование в реальных приложениях:

Абстракция

Абстракция помогает скрыть детали реализации класса или метода от внешнего мира. Таким образом, мы можем избежать раскрытия ненужной информации/данных.
Мы достигаем абстракции, используя абстрактные классы и интерфейсы. Известно, что класс является абстрактным только в том случае, если он имеет один или несколько абстрактных методов, которые только объявлены и предназначены для реализации дочерними классами или подклассами.
Теперь давайте посмотрим на абстракцию в Java с помощью примера кода № 1.1:

public interface Shape {
  public double getArea();
}

public class Circle implements Shape {
  private double radius;

  public Circle(double radius) {
    this.radius = radius;
  }

  @Override
  public double getArea() {
    return Math.PI * radius * radius;
  }
}

public class Square implements Shape {
  private double side;

  public Square(double side) {
    this.side = side;
  }

  @Override
  public double getArea() {
    return side * side;
  }
}

public class Main {
  public static void main(String[] args) {
    Shape circle = new Circle(27);
    Shape square = new Square(18);

    System.out.println("Circle area: " + circle.getArea());
    System.out.println("Square area: " + square.getArea());
  }
}

В приведенном выше примере у нас есть 3 класса (Круг, Квадрат и Основной) и 1 интерфейс (Форма).
Интерфейс Shape определяет объявленный, но не определенный метод getArea(), который возвращает нам область. формы. Классы Circle и Square наследуют интерфейс Shape и переопределяют метод getArea() в соответствии с их формулой размера.
Здесь класс Main создает экземпляры классов Circle и Square. Класс Main знает только, что объекты Circle и Square являются объектами Shape и могут возвращать их площадь, но не знает, как вычисляется площадь. Детали реализации метода getArea() скрыты от класса Main и других классов, использующих интерфейс Shape.
Вот как мы реализуем абстракцию в Java. Если у вас есть какие-либо вопросы, связанные с абстракцией, прокомментируйте свой запрос в комментариях. Давайте рассмотрим следующую тему Наследование.

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

Наследование используется для получения свойств и методов родительского класса в дочернем классе. Наследование в Java — это механизм, при котором один класс приобретает все свойства и поведение родительского класса. Это важная часть ООП. Идея заключается в том, что вы можете создавать новые классы, основанные на существующих классах.
Например, если мы хотим получить доступ к переменным и методу родительского класса в дочернем классе, это будет сделано с помощью ключевое слово «расширяет».
Java не поддерживает множественное наследование. Это означает, что вы не можете расширить несколько классов в одном классе. Но один класс может быть расширен несколькими классами. Этот родительский класс Means может быть расширен классом Child-1 и классом Child-2 одновременно.

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 {
  private String breed;

  public Dog(String name, int age, String breed) {
    super(name, age);
    this.breed = breed;
  }

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

public class Main {
  public static void main(String[] args) {
    Dog dog = new Dog("Buddy", 5, "Golden Retriever");

    dog.eat();
    dog.sleep();
    dog.bark();
  }
}

В приведенном выше примере класс Animal является родительским классом, а класс Dog — дочерним классом. Класс Dog расширяет класс Animal с помощью ключевого слова extends. Класс Dog наследует два свойства (имя и возраст) и методы eat() и sleep() от класса Animal. strong> класс.
Класс Dog также имеет свое поле породы и свой метод bark(). В конструкторе класса Dog оператор super(name, age) вызывает конструктор класса Animal для установки имени и возраста. поля объекта Dog.
Класс Main создает экземпляр класса Dog и вызывает его eat. strong>(), sleep() и bark(). Объект Dog может получить доступ к унаследованным полям имени и возраста, а также к методам eat() и sleep() объекта Animal. strong>, а также его поле породы и метод bark().

Полиморфизм

Полиморфизм в объектно-ориентированном программировании — это термин, который относится к способности объекта принимать несколько форм или иметь несколько вариантов поведения.
Он позволяет обрабатывать несколько объектов разных типов так, как если бы они были одного типа, что позволяет необходимо написать программу, которая может единообразно работать с различными объектами.
Полиморфизм обеспечивает некоторые из ключевых особенностей ООП, а именно возможность повторного использования кода, расширяемость и гибкость. Давайте поговорим о полиморфизме в Java. Для достижения полиморфизма в Java мы используем переопределение и перегрузку методов.
1. Переопределение метода:
При переопределении метода мы переопределяем унаследованный метод/функцию из родительского класса/суперкласса. В дочернем классе мы создаем функции с тем же именем, но с разными функциями. Переопределение метода также известно как полиморфизм времени выполнения. Давайте посмотрим на переопределение метода на примере кода:

class Animal {
    public void makeSound() {
        System.out.println("The animal makes a sound");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("The dog barks");
    }
}
  
public class Main {
    public static void main(String[] args) {
   
        Animal animal = new Dog();        
        animal.makeSound(); // Output: The dog barks
    
    }
}

Здесь мы можем использовать класс Animal, у которого есть метод makeSound(). Аналогично, в классе Dog есть метод с таким же именем makeSound(). Таким образом, мы можем переопределить методы родительского класса и использовать остальные свойства родительского класса в соответствии с нашими потребностями.
2. Перегрузка методов.
При перегрузке методов два или более метода с одинаковыми именами определяются в одном классе. Методы можно различать по количеству параметров каждого метода. Перегрузка метода также известна как полиморфизм времени компиляции. Давайте изучим перегрузку метода на примере: -

public class Main {
    public void addNumbers(int a, int b) {
        System.out.println("The Sum of given numbers is "+(a+b));
    }
    public void addNumbers(int a, int b, int c) {
        System.out.println("The Sum of given numbers is "+(a+b+c));
    }
    public void addNumbers(int a, int b, int c, int d) {
        System.out.println("The Sum of given numbers is "+(a+b+c+d));
    }
    public static void main(String[] args) {
   
        Main obj = new Main();        
        obj.addNumbers(2,3); //Prints The Sum of given numbers is 5
        obj.addNumbers(2,3,4); //Prints The Sum of given numbers is 9
        obj.addNumbers(2,3,4,5); //Prints The Sum of given numbers is 14
    }
}

Таким образом, в приведенном выше примере мы видим, что класс Main имеет три метода с одинаковыми именами addNumbers(), но все три метода имеют разное количество параметров. Вот как мы можем определить несколько методов с одинаковыми именами, но с разным количеством параметров для достижения желаемой функциональности.

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

Инкапсуляция — это термин в объектно-ориентированном программировании (ООП), который используется для хранения внутренних рабочих скрытых и рабочих данных в одном блоке (классе). Инкапсуляция — это практика объединения данных и предоставления четко определенного интерфейса для взаимодействия с объектом.
Модификаторы доступа используются для достижения инкапсуляции в Java (общедоступной, частной и защищенной). Используя эти модификаторы доступа, мы можем контролировать видимость данных и функции/методы внутри класса.
Таким образом, мы можем ограничить доступ к внешнему коду внутри нашего класса, обеспечив его целостность и согласованность внутреннего состояния. Давайте рассмотрим инкапсуляцию на примере:

public class Employee {
    private String name;
    public Employee(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

Как видно из примера, имя переменной имеет модификатор доступа private, поэтому мы не можем установить ее значение напрямую. Мы можем изменить и использовать его значение с помощью методов setter и getter, которые могут быть следующими:

Employee emp = new Employee("Mubashir");
System.out.println(emp.getName()); //Prints Mubashir
emp.setName("Mubashir Ibrahim");
System.out.println(emp.getName()); //Prints Mubashir Ibrahim

Здесь мы использовали метод emp.getName() для доступа к значению переменной «name». Точно так же для изменения значения переменной «name» мы использовали метод emp.setName() и обновили значение переменной «name». на «Мубашир Ибрагим».

На сегодня достаточно, дайте мне знать о ваших предложениях в разделе комментариев. Я постараюсь ответить на ваши вопросы как можно скорее.
Спасибо за внимание, в будущем мы рассмотрим больше тем, иншаАллах.