Что такое ООП?
Объектно-ориентированное программирование (ООП) — это парадигма программирования, которая революционизирует способы организации и структурирования кода. JavaScript, универсальный язык, полностью охватывает концепции ООП, позволяя разработчикам создавать надежные и масштабируемые приложения. В этой статье мы рассмотрим фундаментальные принципы ООП в JavaScript, сопровождаемые наглядными примерами, которые воплотят эти концепции в жизнь.
Что такое ООП простыми словами? Объектно-ориентированное программирование основано на концепции объектов. Источник: (Фунтех)
Объекты JavaScript: строительные блоки
В JavaScript объект — это мощная конструкция, объединяющая набор свойств, каждое из которых представлено парой ключ-значение. Ключи — это строки, которые служат именами свойств, а значения могут быть любого типа данных, включая другие объекты.
В JavaScript объекты — это главное. Если вы понимаете объекты, вы понимаете JavaScript. (источник: w3school)
давайте рассмотрим пример объекта в JavaScript:
const person = { name: 'Miraz Hossain', age: 39, greet: function() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } }; person.greet(); // Output: Hello, my name is Miraz Hossain and I am 39 years old.
В этом примере мы создаем объект person
со свойствами name
и age
, а также метод greet
, выводящий на консоль дружеское приветствие.
Для доступа к свойствам объекта мы можем использовать запись через точку или скобки:
console.log(person.name); // output: 'Miraz Hossain' console.log(person['age']); // output: 39
Классы: чертеж объектов
Классы предоставляют схему для создания объектов с похожими свойствами и поведением. В JavaScript вы можете определять классы, используя ключевое слово class
. Давайте посмотрим на пример:
class Person { constructor(name, age) { this.name = name; this.age = age; } greet() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } }
В этом случае мы определяем класс Person
с конструктором, который принимает два аргумента name
и age
. Конструктор инициализирует два свойства объекта name
age
. Кроме того, мы определяем метод greet
, который выводит приветствие на консоль, используя свойства name
и age
.
Чтобы создать объект класса Person
, мы используем ключевое слово new
:
const person = new Person('Miraz', 39.5); person.greet(); // output: Hello, my name is Miraz and I am 39.5 years old.
Наследование: повторное использование кода
Наследование позволяет создавать новые классы на основе существующих. Новые классы основаны на существующих. Новый класс, известный как подкласс, наследует свойства и методы существующего класса, известного как суперкласс.
JavaScript реализует наследование через ключевое слово extends
. Рассмотрим пример:
class Student extends Person { constructor(name, age, grade) { super(name, age); this.grade = grade; } study() { console.log(`${this.name} is a ${this.grade} in JavaScript.`); } }
В этом примере мы определяем класс Student
, который расширяет класс Person
. Класс Student
имеет собственный конструктор, принимающий три аргумента: name
age
и grade
. Конструктор вызывает метод super
, который, в свою очередь, вызывает конструктор класса Person
и инициализирует свойства name
и age
. Кроме того, класс Student
представляет метод study
, который выводит сообщение на консоль.
Чтобы создать объект класса Student
, мы снова используем ключевое слово new
:
const student = new Student('Tony Stark', 52, 'Pro'); student.greet(); // Output: Hello, my name is Tony Stark and I am 52 years old. student.study(); // output: Tony Stark is a Pro in JavaScript.
Мы видим, что класс Student
наследует метод greet
от класса Person
, а также вводит свой собственный метод study
.
Инкапсуляция: сокрытие данных
Инкапсуляция включает в себя практику сокрытия внутренних деталей объекта и предоставления общедоступного интерфейса для взаимодействия. Это не позволяет внешнему коду напрямую изменять внутреннее состояние объекта, эффективно устраняя ошибки и другие проблемы. JavaScript использует замыкания для достижения инкапсуляции. Рассмотрим пример:
function createCounter() { let count = 0; return { increment() { count++; }, decrement() { count--; }, getCount() { return count; } }; } const counter = createCounter(); console.log(counter.getCount()); //Output: 0 counter.increment(); console.log(counter.getCount()); //Output: 1 counter.decrement(); console.log(counter.getCount()); //Output: 0
Совет для профессионалов: не забудьте поставить запятую перед каждым объектом
В этом примере мы определяем функцию createCounter
, которая возвращает объект тремя методами increment
decrement
и getCount
. Переменная count
объявляется внутри функции createCounter
и остается недоступной снаружи объекта. Методы increment
и decrement
изменяют переменную count
, а метод getCount
извлекает ее текущее значение.
Полиморфизм: один интерфейс, множество реализаций
Полиморфизм относится к способности объектов, принадлежащих к разным классам, обрабатываться так, как если бы они были объектами одного и того же класса. JavaScript использует полиморфизм через интерфейсы.
Рассмотрим следующий пример:
class Shape { draw() { console.log('Drawing shape...'); } } class Circle extends Shape { draw() { console.log('Drawing circle...'); } } class Square extends Shape { draw() { console.log('Drawing square...'); } } function drawShapes(shapes) { shapes.forEach(shape => { shape.draw(); }); } const shapes = [ new Circle(), new Square(), new Circle(), new Square() ]; drawShapes(shapes);
В этом примере мы определяем класс Shape
с методом draw
. Кроме того, мы определяем классы Circle
и Square
, которые расширяют класс Shape
, каждый из которых переопределяет метод draw
своими уникальными реализациями.
Далее мы определяем функцию drawShapes
, которая принимает массив объектов Shape
и вызывает соответствующие методы draw
. Мы создаем массив, содержащий объекты Circle
и Square
, передавая его в функцию drawShapes
. Примечательно, что, несмотря на то, что объекты принадлежат разным классам, с ними можно обращаться так, как если бы они были экземплярами класса Shape
.
Пример объединения полномочий
Чтобы закрепить наше понимание объектов, классов, наследования и полиморфизма в JavaScript, давайте рассмотрим наглядный пример:
class Animal { constructor(name) { this.name = name; } eat() { console.log(`${this.name} is eating`); } sleep() { console.log(`${this.name} is sleeping`); } repeat() { console.log('Just Repeat And Do It Again Until Done'); } } class Cat extends Animal { constructor(name) { super(name); } meow() { console.log(`${this.name} says meow.`); } sleep() { console.log(`${this.name} is sleeping`); } } class Dog extends Animal { constructor(name) { super(name); } brak() { console.log(`${this.name} says woof`); } eat() { console.log(`${this.name} is eating Nuts`); } } let animals = [ new Cat('Tom'), new Dog('Tommy'), new Cat('Anna'), new Dog('Dollar') ]; for (let animal of animals) { animal.eat(); animal.sleep(); if (animal instanceof Cat) { animal.meow(); } if (animal instanceof Dog) { animal.brak(); } }
В этом подробном примере мы определяем базовый класс с именем Animal
с методом constructor
, который принимает параметр name
и устанавливает его как переменную экземпляра. Класс Animal
также имеет три метода eat
sleep
repeat
Впоследствии мы определяем два подкласса Cat
Dog
. Оба класса наследуются от Animal
, используя ключевое слово extends
. Каждый из них имеет свои собственные методы constructor
, которые вызывают super
для вызова конструктора родительского класса и присваивают переменную экземпляра name
.
Класс Cat
представляет метод meow
, который выводит сообщение на консоль. Кроме того, он переопределяет метод sleep
, унаследованный от родительского класса. С другой стороны, класс Dog
имеет метод bark
, который выводит сообщение на консоль. Он также переопределяет метод eat
, унаследованный от родительского класса.
Затем мы создаем массив из Animal
объектов, включающий как Cat
, так и Dog
экземпляров. Мы перебираем массив, вызывая методы eat
и sleep
для каждого объекта. Кроме того, мы используем оператор instanceof
, чтобы определить, принадлежит ли объект к классу Cat
или Dog
, после чего вызываем соответствующий метод (meow
для объектов Cat
и bark
для объектов Dog
).
На этом всеобъемлющем примере мы видим, как объекты, классы, наследование и полиморфизм гармонично сочетаются в JavaScript для создания повторно используемого и расширяемого кода.
Заключение
В этой статье мы приступим к изучению основных концепций объектно-ориентированного программирования (ООП) в JavaScript. Мы рассмотрели объекты, классы, наследование, инкапсуляцию и полиморфизм, углубившись в их определения и примеры реализации. Вооружившись этими знаниями, мы можем писать поддерживаемый и повторно используемый код JavaScript, повышая качество наших приложений. Удачного кодирования!
«Не будь программистом, будь решателем проблем»