@Lobanov

Может ли дочерний класс иметь приватные методы?

Всем привет)

Ребят, ковыряю ООП в JS и наткнулся на одну непонятную ошибку.

Есть родительский класс Timer с конструктором и несколькими методами, я от него наследуюсь, создавая NiceTimer класс, которому прописываю несколько своих методов, и один из них решаю сделать статическим. Создаю 1 экземпляр класса Timer и еще один экземпляр NiceTimer, в результате получаю ошибку:

Uncaught TypeError: Receiver must be an instance of class NiceTimer


Вот код, в нем есть метод #declension, который я хочу заюзать в методе formatClock:
window.addEventListener('load', function () {
  let timer1 = new Timer('.timer1', 10);
  let timer2 = new NiceTimer('.timer2', 5000);

  document.querySelector('.getSale').addEventListener('click', function () {
    this.disabled = true;
    this.innerHTML = 'Скидка ваша!';
    timer2.stop();
  });
});

class Timer {
  constructor(selector, time) {
    this.box = document.querySelector(selector);
    this.time = time;
    this.interval = null;
    this.render();
    this.start();
  }

  start() {
    this.interval = setInterval(() => {
      this.tick();
    }, 1000);
  }

  stop() {
    clearInterval(this.interval);
  }

  tick() {
    this.time--;
    this.render();

    if (this.time < 1) {
      this.stop();
    }
  }

  render() {
    this.box.innerHTML = this.time;
  }
}

class NiceTimer extends Timer {
  constructor(selector, time) {
    super(selector, time);
  }

  //   tick() {
  //     super.tick();
  //   }

  render() {
    let formatClock = this.formatClock();
    let countdown = '';

    for (let key in formatClock) {
      countdown += `${formatClock[key].time} ${formatClock[key].word} `;
    }

    this.box.innerHTML = countdown;
  }

  formatClock() {
    let clock = this.calcClock();
    let wordForms = this.wordForms();

    return {
      h: {
        time: clock.h,
        word: this.#declension(wordForms.hours, clock.h),
      },
      m: {
        time: clock.m,
        word: this.#declension(wordForms.minutes, clock.m),
      },
      s: {
        time: clock.s,
        word: this.#declension(wordForms.seconds, clock.s),
      },
    };
  }

  calcClock() {
    let h = parseInt(this.time / 3600);
    let hs = this.time % 3600;
    let m = parseInt(hs / 60);
    let s = hs % 60;

    return { h, hs, m, s };
  }

  #declension(forms, val) {
    const cases = [2, 0, 1, 1, 1, 2];
    return forms[
      val % 100 > 4 && val % 100 < 20 ? 2 : cases[val % 10 < 5 ? val % 10 : 5]
    ];
  }

  wordForms() {
    return {
      days: ['день', 'дня', 'дней'],
      hours: ['час', 'часа', 'часов'],
      minutes: ['минута', 'минуты', 'минут'],
      seconds: ['секунда', 'секунды', 'секунд'],
    };
  }
}


Я в ООП не очень силен, копаю эту тему и пытаюсь разобраться. Сколько изучаю тему, казалось, что у дочернего класса можгут быть собственные приватные методы, дабы реализовывать какую-то свою внутреннюю логику, но вот эта ошибка меня что-то сбила с толку. Буду благодарен за подсказку.
  • Вопрос задан
  • 324 просмотра
Решения вопроса 1
Lynn
@Lynn
nginx, js, css
Очень поверхностно получается так:
  1. У объекта this прототип указывает на NiceTimer, в частности все методы берутся из NiceTimer, но…
  2. при вызове родительского конструктора (вызов super()) приватные свойства и методы ещё не созданы и поэтому вызов this.#declension вызывает ошибку.


Всё это формально описано примерно тут:
https://tc39.es/ecma262/multipage/ecmascript-langu...

В частности родительский конструктор вызывается на 6 шаге, а приватные свойства создаются на 11 шаге.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы