Можно ли вызвать переопределенный метод в экземпляре дочернего класса ES 2015? - PullRequest
1 голос
/ 25 октября 2019

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

Вот простой код:

class Car {
  constructor(make,model) {
    this.make = make
    this.model = model
  }

  emitsCarbon() {
    return true
  }

}

class Hybrid extends Car {
  constructor(...args) {
    super(...args)
  }
  emitsCarbon() {
    return false
  }
}

let car1 = new Hybrid('toyota', 'prius')

car1.emitsCarbon() // returns false

ЧтоМне интересно, есть ли способ вызвать оригинальный метод emitsCarbon(), который возвращает true (из родительского класса) в экземпляре дочернего класса?

Мое предположение будет отрицательным, если он будет переопределенЯ должен был бы переопределить метод снова в экземпляре car1, чтобы он возвращал true при вызове функции.

Недостаток знаний, которые я ищу, заключается в следующем: в JavaScript можно ссылатьсясоздайте резервную копию уровня наследования классов и просмотрите все свойства родительского класса (методы и т. д.), заданные для экземпляра дочернего классаПохоже, что это возможно в других языках (например, Java), однако у меня не так много опыта работы с этими языками.

Наконец, полезно ли это, т. Е. Нужно ли большеосторожнее с переопределением свойств, которые не должны быть переопределены, я менее уверен. Я думаю, что не следует. Тем не менее, полезно лучше понять перемещение уровня в классах и иерархии наследования классов в целом.

Это не дубликат: Как вызвать родительский метод из дочернего класса в javascript?

Я понимаю вызов родительского метода в дочернем классе, однако я не понимаю вызова (если это вообще возможно, что, по-видимому, нет) родительского метода в дочернем классе экземпляр .

Ответы [ 4 ]

1 голос
/ 25 октября 2019

Это JavaScript, так что вы можете. В любом случае, нет никаких классов, только наследование прототипа с некоторым синтаксическим сахаром над ним.

Какой из них вы хотите назвать: Car 'emitsCarbon конкретно? Это будет

Car.prototype.emitsCarbon.call(car1);

Класс вашего объекта 'класс прямого предка' emitsCarbon в целом?

car1.__proto__.__proto__.emitsCarbon.call(car1);

(Вы не должны иметь прямой доступ к __proto__, ноничто на самом деле не останавливает вас, кроме общих правил и рекомендаций).

Кроме того, гибриды действительно выделяют углерод. Просто примечание.

0 голосов
/ 25 октября 2019

Другой ответ подходит для случаев, когда вы можете изменить дочерний класс.

Но поскольку в оригинальном сообщении упоминается «... экземпляр дочернего класса», а не «данныйдочерний класс », то вы можете сделать то же самое, даже если вы не можете изменить дочерний класс с помощью <ParentClass>.prototype.<methodName>.

class A {
  foo () {
    return 0;
  }
}

class B extends A {
  foo () {
    return 1;
  }
}

let b = new B();
console.log(b.foo()); // 1
console.log(A.prototype.foo()); // 0

Для методов, для которых требуется контекст this, используйте call для вызова.

class A {
  constructor(f) {
    this.f = f;
  }

  foo(ff) {
    return this.f + ff + 1;
  }
}

class B extends A {
  foo(ff) {
    return this.f + ff + 2;
  }
}

let b = new B(10);
console.log(b.foo(5)); // 17
console.log(A.prototype.foo.call(b, 5)); // 16
0 голосов
/ 25 октября 2019

Когда дочерний объект переопределяет родительские методы, он всегда будет использовать переопределенную версию , если вы не используете ключевое слово 'super' в определении метода самого дочернего элемента.

Вызов родительского метода через дочерний объект, который уже переопределяет этот метод, невозможен.

0 голосов
/ 25 октября 2019

Не могу поверить, что это не дубликат, но я не могу его найти (все существующие вопросы и ответы имеют дело с функциями конструктора старого стиля), так что ...

Просто используйте super:

class A {
  foo () {
    return 0;
  }
}

class B extends A {
  foo () {
    return 1;
  }

  bar () {
    return super.foo();
  }
}

const b = new B();
b.foo() // 1
b.bar() // 0

Существуют некоторые ограничения, использование super не позволит вам изменять свойства только для чтения.

Подробнее см. Статью MDN подробности.

...