TypeScript: Абстрактные классы
Когда нам нужно определить общее поведение для нескольких классов, удобно использовать абстрактные классы, которые мы разберем в этом уроке.
Абстрактные классы хоть и не могут быть созданы напрямую, однако они могут быть наследованы. Еще они могут указать явно, какой метод должен быть реализован в наследниках:
abstract class CustomFile {
protected name: string;
protected size: number;
constructor(name: string, size: number) {
this.name = name;
this.size = size;
}
sizeInKb(): number {
return this.size / 1024;
}
}
class ImageCustomFile extends CustomFile {
constructor(name: string, size: number) {
super(name, size);
}
}
Чтобы выносить из классов общую часть кода, абстрактные классы активно используются для построения архитектуры приложения и фреймворков. Например, в React есть класс Component
, который может быть представлен как абстрактный класс. Мы не можем создать его напрямую, но он требует от наследников реализации метода render
. Это позволяет создавать компоненты, которые будут рендериться при инициализации:
abstract class Component {
abstract render(): void;
constructor() {
this.render();
}
}
Задание
Создайте абстрактный класс Clock
, который будет содержать общую логику для классов часов с разными форматами вывода времени: 12-часовой и 24-часовой.
В общей логике должно быть хранение данных: часы hours
, минуты minutes
и секунды seconds
. Так же в общую логику входит метод tick()
, который при каждом вызове увеличивает секунду на единицу. Если секунда увеличивается до значения 60, то увеличивается минута на 1, а секунда сбрасывается до 0. То же самое с минутами и часами: если значение минут увеличивается до 60, то увеличивается значение текущего часа, а минуты сбрасываются до 0. Если значение часа увеличивается до 24, то происходит сброс этого значения до 0.
Начальное значение времени задается при создании объекта. Первым параметром в конструктор передается текущий час, вторым минуты, третьим секунды.
Абстрактный класс Clock
должен требовать от своих наследников реализацию метода render()
.
// 24-часовой формат
class Clock24 extends Clock {
render(): string {
const currentHour = this.hours % 24;
const hours = currentHour.toString().padStart(2, '0');
const minutes = this.minutes.toString().padStart(2, '0');
return `${hours} : ${minutes}`;
}
}
const clock24 = new Clock24(23, 59, 59);
console.log(clock24.render()); // => '23 : 59'
clock24.tick();
console.log(clock24.render()); // => '00 : 00'
// 12-часовой формат
class Clock12 extends Clock {
render(): string {
const timeType = this.hours > 12 ? 'PM' : 'AM';
let currentHour = this.hours > 12 ? this.hours - 12 : this.hours;
if (timeType === 'AM' && this.hours === 0) {
currentHour = 12;
}
const hours = currentHour.toString().padStart(2, '0');
const minutes = this.minutes.toString().padStart(2, '0');
return `${hours} : ${minutes} ${timeType}`;
}
}
const clock12 = new Clock12(23, 59, 59);
console.log(clock12.render()); // => '11 : 59 PM'
clock12.tick();
console.log(clock12.render()); // => '12 : 00 AM'
Упражнение не проходит проверку — что делать? 😶
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя 🤔
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно 🙄
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Полезное
Определения
Абстрактный класс — это класс, который не может быть создан напрямую. Он предназначен только для наследования. Для создания абстрактного класса используется ключевое слово
abstract
.