Skip to content

Практическая работа №5

Объекты, Классы и Наследование в JavaScript

Section titled “Объекты, Классы и Наследование в JavaScript”

Цель работы:

  • Закрепить теоретические знания об Объектно-Ориентированном Программировании (ООП) в контексте JavaScript.
  • Научиться использовать современный синтаксис классов (class) для создания объектов.
  • Освоить механизм наследования (extends) и вызова родительского конструктора (super()).
  • Научиться применять геттеры и сеттеры для контроля доступа к свойствам объектов.

Основные теоретические положения

Section titled “Основные теоретические положения”

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

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

В JavaScript классы являются, по сути, “синтаксическим сахаром” над существующим прототипным наследованием, но они предоставляют более чистый и привычный для многих разработчиков способ создания объектов.

Класс объявляется с помощью ключевого слова class.

class Animal {
// Конструктор — специальный метод для создания и инициализации объекта
constructor(name, species) {
this.name = name;
this.species = species;
}
// Метод класса
makeSound(sound) {
console.log(`${this.name} (${this.species}) издает звук: ${sound}`);
}
}
// Создание экземпляра класса (объекта)
const dog = new Animal("Бобик", "Собака");
dog.makeSound("Гав-гав"); // Вывод: Бобик (Собака) издает звук: Гав-гав

3. Наследование и ключевое слово super()

Section titled “3. Наследование и ключевое слово super()”

Наследование позволяет создать новый класс, который является специализированной версией другого класса. Для этого используется ключевое слово extends.

Класс Dog наследует все свойства и методы класса Animal.

class Dog extends Animal {
constructor(name, breed) {
// 1. Вызов конструктора родительского класса
// Это ОБЯЗАТЕЛЬНОЕ условие в дочернем классе
super(name, "Собака");
// 2. Инициализация собственных свойств
this.breed = breed;
}
// Переопределение метода родительского класса (Полиморфизм)
makeSound() {
// Вызов метода родительского класса
super.makeSound("Гав-гав");
}
// Собственный метод
fetch() {
console.log(`${this.name} приносит палку.`);
}
}
const rex = new Dog("Рекс", "Немецкая овчарка");
rex.makeSound(); // Вывод: Рекс (Собака) издает звук: Гав-гав
rex.fetch(); // Вывод: Рекс приносит палку.

Ключевое слово super используется в двух случаях:

  1. В конструкторе дочернего класса: super(...) вызывает конструктор родительского класса. Важно: super() должен быть вызван до использования this в конструкторе дочернего класса.
  2. В методах дочернего класса: super.methodName(...) вызывает метод с тем же именем из родительского класса.

Геттеры (Getters) и Сеттеры (Setters) — это специальные методы, которые позволяют контролировать доступ к свойствам объекта. Они выглядят как обычные свойства, но при чтении или записи значения фактически вызывается функция.

МетодКлючевое словоНазначение
ГеттерgetВызывается при попытке получить значение свойства. Используется для вычисления значения или для возврата приватного свойства.
СеттерsetВызывается при попытке установить значение свойства. Используется для валидации данных перед их сохранением.
class Product {
constructor(name, price) {
this.name = name;
// Приватное свойство (по соглашению)
this._price = price;
}
// Геттер для получения цены
get price() {
return this._price;
}
// Сеттер для установки цены с валидацией
set price(newPrice) {
if (newPrice < 0) {
console.error("Цена не может быть отрицательной.");
return;
}
this._price = newPrice;
}
}
const laptop = new Product("Ноутбук", 1200);
// Вызов геттера
console.log(laptop.price); // 1200
// Вызов сеттера
laptop.price = 1500;
console.log(laptop.price); // 1500
// Попытка установить невалидное значение
laptop.price = -100; // Вывод: Цена не может быть отрицательной.
console.log(laptop.price); // 1500 (значение не изменилось)

Для каждого задания необходимо:

  1. Написать программу на языке программирования JavaScript (в одном файле, например, oop_practice.js).
  2. Произвести отладку программы и продемонстрировать работу всех требуемых функций, выводя результаты в консоль.
  3. Обязательно использовать синтаксис class, extends, super(), get и set.

Задания для выполнения

Section titled “Задания для выполнения”

Задание 1. Базовый класс и Геттеры/Сеттеры (Инкапсуляция)

Section titled “Задание 1. Базовый класс и Геттеры/Сеттеры (Инкапсуляция)”

Создайте класс Person (Человек), который будет служить базовой моделью.

  1. Класс Person:

    • Создайте класс Person с конструктором, который принимает и инициализирует свойства firstName, lastName и age.
    • Добавьте метод getFullName(), который возвращает полное имя человека.
    • Добавьте геттер age для получения значения свойства _age (используйте префикс _ для свойства, чтобы показать, что оно должно быть “приватным” по соглашению).
    • Добавьте сеттер age, который выполняет следующую валидацию:
      • Если переданное значение newAge меньше 0 или больше 120, выведите в консоль сообщение об ошибке и не изменяйте свойство.
      • В противном случае, установите значение свойства _age.
  2. Тестирование Person:

    • Создайте два экземпляра класса Person.
    • Выведите в консоль полное имя каждого человека, используя метод getFullName().
    • Проверьте работу геттера, выведя в консоль возраст одного из объектов через синтаксис свойства (например, person1.age).
    • Проверьте работу сеттера, установив корректный возраст (например, person1.age = 30).
    • Проверьте работу валидации сеттера, попытавшись установить некорректный возраст (например, person1.age = 150).

Задание 2. Наследование и ключевое слово super()

Section titled “Задание 2. Наследование и ключевое слово super()”

Создайте класс Employee (Сотрудник), который наследует функциональность от класса Person.

  1. Класс Employee:

    • Создайте класс Employee, который наследуется от класса Person с помощью ключевого слова extends.
    • Конструктор класса Employee должен принимать firstName, lastName, age, а также новые свойства position (должность) и salary (зарплата).
    • Внутри конструктора Employee обязательно вызовите конструктор родительского класса Person с помощью super(firstName, lastName, age).
    • Инициализируйте собственные свойства position и salary.
    • Добавьте метод getAnnualSalary(), который возвращает годовую зарплату (12 * salary).
    • Переопределите метод getFullName() из родительского класса, чтобы он возвращал полное имя вместе с должностью, например: "Иван Петров (Менеджер)".
  2. Тестирование Employee:

    • Создайте два экземпляра класса Employee.
    • Выведите в консоль полное имя и должность одного из сотрудников, используя переопределенный метод getFullName().
    • Выведите в консоль годовую зарплату второго сотрудника.
    • Проверьте, что вы все еще можете использовать геттер/сеттер age из родительского класса Person для объектов Employee.

Задание 3. Иерархия классов с дополнительными Геттерами/Сеттерами

Section titled “Задание 3. Иерархия классов с дополнительными Геттерами/Сеттерами”

Создайте класс Manager, который наследуется от Employee, и добавьте в него дополнительную логику инкапсуляции.

  1. Класс Manager:

    • Создайте класс Manager, который наследуется от класса Employee.
    • Конструктор Manager должен принимать все свойства Employee, а также новое свойство teamSize (количество человек в команде).
    • Обязательно используйте super(...) для передачи всех родительских свойств.
    • Добавьте геттер teamSize для получения значения свойства _teamSize.
    • Добавьте сеттер teamSize, который выполняет следующую валидацию:
      • Если переданное значение newSize не является положительным числом (меньше или равно 0), выведите в консоль сообщение об ошибке и не изменяйте свойство.
      • В противном случае, установите значение свойства _teamSize.
  2. Тестирование Manager:

    • Создайте один экземпляр класса Manager.
    • Выведите в консоль его полное имя (включая должность) и годовую зарплату.
    • Проверьте работу сеттера teamSize, установив корректное значение (например, manager1.teamSize = 5).
    • Проверьте работу валидации, попытавшись установить некорректное значение (например, manager1.teamSize = 0).
    • Продемонстрируйте, что объект Manager имеет доступ к всем методам и свойствам своих родительских классов (Person и Employee).

  1. Объясните, в чем заключается принцип инкапсуляции в ООП и как он реализуется в JavaScript с помощью геттеров и сеттеров.
  2. Какова основная функция ключевого слова extends при работе с классами в JavaScript?
  3. Почему в конструкторе дочернего класса обязательно нужно вызывать super() до использования ключевого слова this?
  4. Приведите пример, когда использование сеттера является более предпочтительным, чем прямое изменение свойства объекта.
  5. В чем разница между вызовом super() в конструкторе и вызовом super.methodName() в методе дочернего класса?

Рекомендуемая литература

Section titled “Рекомендуемая литература”
  1. Классы в JavaScript - Современный учебник JavaScript.
  2. Наследование классов - Современный учебник JavaScript.
  3. Геттеры и Сеттеры - Современный учебник JavaScript.
  4. Class - MDN Web Docs - Официальная документация Mozilla Developer Network.
  5. extends - MDN Web Docs - Официальная документация Mozilla Developer Network.