Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чи можна успадковувати приватні властивості?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Ні, приватні поля (`#field`) **не успадковуються**: коли клас-нащадок звертається до `this.#secret`, оголошеного в батьківському класі, JavaScript кидає `SyntaxError`, бо кожен клас має власний, повністю ізольований простір приватних імен. **Ключове:** щоб поділитися прихованими даними з нащадками, використовують не `#field`, а домовленість про `_field`, геттери/сеттери батьківського класу або `WeakMap` із контрольованим доступом.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Приклад: приватне поле в батьківському класі недоступне в нащадку ```javascript class Parent { #secret = "parent secret"; showSecret() { console.log(this.#secret); } } class Child extends Parent { reveal() { console.log(this.#secret); // Помилка } } const c = new Child(); c.showSecret(); // "parent secret" c.reveal(); // SyntaxError: Private field '#secret' must be declared in an enclosing class ``` Пояснення: - Приватне поле `#secret` "належить" лише класу `Parent`. - Клас `Child` навіть **не знає про його існування**. - Тому доступ до `this.#secret` всередині `Child` неможливий. --- ## 2. Як це працює під капотом Коли ти оголошуєш `#field`, JavaScript створює **унікальний прихований ідентифікатор**, доступний **лише всередині тіла цього класу**. Тобто навіть якщо ти використовуєш однакове ім'я `#secret` у двох класах, це **два різних поля**, не пов'язані між собою: ```javascript class Parent { #secret = "parent"; getParentSecret() { return this.#secret; } } class Child extends Parent { #secret = "child"; getChildSecret() { return this.#secret; } } const c = new Child(); console.log(c.getParentSecret()); // parent console.log(c.getChildSecret()); // child ``` Тут `#secret` у `Parent` і `#secret` у `Child`, це **дві незалежні властивості**, з однаковим ім'ям, але різними "прихованими ключами". --- ## 3. Чому не можна успадковувати приватні поля Це свідоме рішення авторів мови: - Щоб **зберегти сувору інкапсуляцію** (усе, що починається з `#`, повністю приховане). - Щоб **уникнути конфліктів імен** між приватними властивостями різних класів. - Щоб **спростити оптимізацію** в рушіях (V8, SpiderMonkey тощо). Тому `extends` **успадковує методи**, але не дає доступу до приватних полів батьківського класу. --- ## 4. Як тоді ділитися приватними даними між батьківським класом і нащадком Якщо ти хочеш, щоб **приватні дані були доступні в нащадках**, використай один із таких прийомів: --- ### Варіант 1: використати **protected-подібну домовленість** (`_field`) Це не справжня приватність, але часто використовується на практиці: ```javascript class Parent { _secret = "accessible to subclasses"; showSecret() { console.log(this._secret); } } class Child extends Parent { reveal() { console.log(this._secret); // Працює } } ``` > Тут `_secret`, це просто домовленість "не чіпай цю властивість ззовні". > Вона **не захищена**, але **доступна нащадкам**. --- ### Варіант 2: використати **геттери / сеттери** Батьківський клас може керувати доступом через методи, а нащадок може використовувати ці методи, не знаючи деталей реалізації. ```javascript class Parent { #secret = "parent secret"; getSecret() { return this.#secret; } } class Child extends Parent { reveal() { console.log(this.getSecret()); // Можна отримати через метод } } new Child().reveal(); // parent secret ``` > Таким чином приватність зберігається, але доступ можливий через інтерфейс. --- ### Варіант 3: використати **WeakMap** (альтернатива `#` до ES2022) Це старий, але гнучкий спосіб "приватних" даних із контрольованим доступом. ```javascript const privates = new WeakMap(); class Parent { constructor() { privates.set(this, { secret: "shared secret" }); } get _data() { return privates.get(this); } } class Child extends Parent { reveal() { console.log(this._data.secret); // доступний } } new Child().reveal(); // shared secret ``` WeakMap дає змогу приховати дані, але водночас робити їх **доступними в нащадках**. --- ## 5. Підсумок: порівняння підходів | Підхід | Приватність | Доступ нащадкам | Реальний захист | | --- | --- | --- | --- | | `#field` | Повна | Немає | Абсолютний | | `_field` (за домовленістю) | Часткова | Так | Захисту немає | | `WeakMap` | Майже повна | Так | Так | | Геттер/сеттер | Через інтерфейс | Так | Контрольований | --- ## Короткий висновок > Приватні поля (`#field`) **не успадковуються**. > Кожен клас має **свій власний** приватний простір. > Нащадки **не можуть** напряму звертатися до приватних полів батьківського класу. > Якщо потрібно поділитися приватними даними, використай: > > - `_field` (домовленість), > - геттери/сеттери, > - або `WeakMap` із доступом для нащадків.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.