В объектно-ориентированном программировании на TypeScript управление доступом к свойствам играет ключевую роль для создания надежной архитектуры. Модификатор protected занимает промежуточное положение между public и private.
Члены класса, помеченные как protected, доступны внутри самого класса и во всех его классах-наследниках (подклассах), но остаются закрытыми для внешнего мира (экземпляров класса). Это идеальный инструмент для реализации внутренней логики, которая должна передаваться по наследству, но не должна торчать наружу.
Использование этого модификатора помогает соблюдать принцип инкапсуляции, позволяя расширять функциональность базовых классов без риска нарушить их целостность извне. В этом уроке мы разберем синтаксис, отличия от private и типичные сценарии применения protected при разработке сложных иерархий.
- Модуль 1: Введение в TypeScript
- Модуль 2: Примитивные типы
- Модуль 3: Специальные типы
- Модуль 4: Массивы
- Модуль 5: Кортежи (Tuples)
- Модуль 6: Объекты
- Модуль 7: Функции
- Модуль 8: Union типы
- Модуль 9: Литеральные типы
- Модуль 10: Type Aliases
- Модуль 11: Интерфейсы
- Модуль 12: Type Guards и Narrowing
- Модуль 13: Enums
- Модуль 14: Классы
- Модуль 15: Generics — основы
- Модуль 16: Generics — ограничения
- Модуль 17: Utility Types — базовые
- Модуль 18: Utility Types — работа с Union
- Модуль 19: Utility Types — функции
- Модуль 20: Type Assertions
- Модуль 21: Keyof и Typeof операторы
- Модуль 22: Mapped Types
- Модуль 23: Conditional Types
- Модуль 24: Discriminated Unions
- Модуль 25: Модули и типы
- Модуль 26: Declaration Files
- Модуль 27: Типизация асинхронного кода
- Модуль 28: Практические паттерны
1. Выбор модификатора
В данном задании представлен фрагмент кода на TypeScript, содержащий базовый класс и класс-наследник. Вам необходимо выбрать подходящий модификатор доступа для свойства, чтобы оно было доступно в классе-наследнике, но оставалось закрытым для внешнего кода. Для этого кликните на пропуск и выберите верный вариант из предложенного списка.
class Animal {
input1S name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
bark() {
console.log(`${this.name} barks!`);
}
}2. Объявление protected метода
В этом задании вам нужно исправить ошибку доступа к методу в подклассе, добавив соответствующий модификатор доступа. В классе Vehicle объявлен метод startEngine, который должен быть доступен в подклассе Car, но не извне. Однако в коде пропущено ключевое слово, ограничивающее видимость метода только классом и его наследниками. Вставьте правильный модификатор перед объявлением метода, чтобы код соответствовал принципам инкапсуляции и компилировался без ошибок.
class Vehicle {
input1S startEngine(): void {
console.log("Engine started");
}
}
class Car extends Vehicle {
public drive(): void {
this.startEngine();
console.log("Car is moving");
}
}
const myCar = new Car();
myCar.drive();3. Ошибка инкапсуляции
В данном фрагменте кода TypeScript допущена ошибка, связанная с нарушением инкапсуляции при использовании модификатора доступа protected. В классе-наследнике определен публичный метод для получения значения protected-свойства, однако в основном коде происходит попытка прямого обращения к этому свойству через экземпляр класса. Найдите строку с ошибкой и исправьте её, заменив обращение на вызов соответствующего публичного метода.
class Animal { protected species: string; constructor(species: string) { this.species = species; }} class Dog extends Animal { public getSpecies(): string { return this.species; }} let myDog = new Dog("Canine");console.log(myDog.species);4. Зоны видимости
Перед вами описания ситуаций доступа к членам класса в TypeScript. Распределите их по категориям модификаторов доступа: Public, Private, Protected. Обратите внимание, где происходит обращение: внутри самого класса, в классе-наследнике или снаружи (из другого кода). Каждый элемент описывает конкретный случай доступа.
5. Доступ при наследовании
Проанализируйте приведённый код на TypeScript, содержащий иерархию классов с использованием модификатора protected. Определите, что произойдёт при попытке компиляции и выполнения этого кода. Обратите внимание на доступ к свойствам с разными модификаторами из разных контекстов.
class Vehicle {
protected vin: string = 'VIN-12345';
public model: string = 'Generic';
protected getVin(): string {
return this.vin;
}
}
class Car extends Vehicle {
public displayInfo(): void {
console.log('Model:', this.model);
console.log('VIN via method:', this.getVin());
console.log('Direct VIN:', this.vin);
}
}
const myCar = new Car();
myCar.displayInfo();
console.log('External model access:', myCar.model);
console.log('External VIN access:', myCar.vin);6. Сборка класса-наследника
Из предложенных строк соберите корректную TypeScript-программу, в которой класс Child расширяет класс Parent и использует его protected метод greet(). Программа должна создать экземпляр Child и вызвать его публичный метод, который обращается к protected методу родителя. Лишние строки (не входящие в решение) включать не нужно.
class Parent { protected greet(): void { console.log('Hello from Parent'); }}class Child extends Parent { public callGreet(): void { this.greet(); }}const child = new Child();child.callGreet();console.log(child.greet());class Another { }7. Поиск защищенных членов
Внимательно изучите приведённый код на TypeScript, который содержит определение класса и его наследника. Ваша задача — выделить кликом все свойства и методы, имеющие модификатор доступа protected. Не отмечайте публичные (public) или приватные (private) члены, а также ключевые слова, имена классов, конструкторы и прочие элементы, не являющиеся protected-свойствами или методами.
class Vehicle {
{{protected~|~t0}} {{maxSpeed~|~t1}}: number = 120;
{{private~|~t2}} {{vin~|~t3}}: string;
{{public~|~t4}} {{brand~|~t5}}: string;
constructor(brand: string, vin: string) {
this.brand = brand;
this.vin = vin;
}
{{protected~|~t6}} {{getMaxSpeed~|~t7}}(): number {
return this.maxSpeed;
}
{{public~|~t8}} {{displayInfo~|~t9}}(): void {
console.log(`Brand: ${this.brand}, VIN: ${this.vin}`);
}
}
class Car extends Vehicle {
{{private~|~t10}} {{isElectric~|~t11}}: boolean;
constructor(brand: string, vin: string, isElectric: boolean) {
super(brand, vin);
this.isElectric = isElectric;
}
{{public~|~t12}} {{showMaxSpeed~|~t13}}(): void {
// Обращение к protected-методу родителя
console.log(`Max speed: ${this.{{getMaxSpeed~|~t14}}()}`);
}
{{protected~|~t15}} {{updateMaxSpeed~|~t16}}(newSpeed: number): void {
this.{{maxSpeed~|~t17}} = newSpeed;
}
}