Возможно ли иметь абстрактный класс в JS?

Я нашел прототип наследования в javascript.

То, что я хотел достичь, - это набросок методов, которые при наследовании должны быть реализованы/определены.

Я хотел бы знать, возможно ли это, и если да, то как.

Ответы

Ответ 1

У JavaScript действительно нет ничего подобного. Как вы сказали, JavaScript прототип ориентирован.


Как говорили другие ответы, конечно, вы можете имитировать это. Но я не вижу достаточной причины для этого. Почему объектно-ориентированные программисты используют интерфейсы и абстрактные классы? Astraction и decoupling. Они позволяют делать всевозможные приятные вещи, такие как методы записи, которые потребляют (принимают в качестве аргументов) и производят (возвращают) значения, которые имеют абстрактные типы - объекты, которые, по крайней мере, удовлетворят некоторый контракт относительно его методов и полей.

В свою очередь, мы получаем другие "приятные вещи", такие как проверки времени компиляции для безопасности типов. Попробуйте передать объект типа Foo методу, который принимает только объекты типа Bar *, и вы получите предупреждение компилятора.

И теперь для фактических объяснений

  • JavaScript позволит вам передать любой объект любой функции. То, что вы делаете с этим объектом внутри функции, может привести к ошибкам во время выполнения, но ничто не остановит вас от передачи произвольных аргументов и даже другого аргумента, чем заявляет функция.
  • Переменные JavaScript не имеют явных типов. Что означает "гарантировать" что какой-то объект имеет некоторый набор методов, когда вам еще нужно выполнить ручную и явную проверку типов?
  • В JavaScript функции не застревают, подчиняясь объектам — они являются первоклассными гражданами языка и могут использоваться как объекты. Так? Функции объекта могут меняться во время выполнения. Вы можете добавить дополнительные функции к объекту или удалить их из объекта (или затенять функцию в прототипе). Таким образом, пока вы не можете изменить объект prototype или constructor после создания (read: new), вы можете изменить свойства объекта.
  • Как и в случае с номером 2, невозможно гарантировать, что функция возвращает, или даже гарантировать, что функция вернет какое-либо значение вообще. Функции не имеют явно декларированной подписи в JavaScript так, как это делают во многих языках OO.

Что вы на самом деле пытаетесь сделать?

Похоже, вы пытаетесь навязать относительную жесткость строго типизированных объектно-ориентированных языков на системе динамического типа JavaScript "relaxed, go-in-flow". ИМХО, это не отличная идея. Может быть, вы могли бы объяснить фактическую проблему, которую пытаетесь решить?

Извините, если это длинный, rant-y или некогерентный. Я уверен, что там есть хотя бы один язык (OCaml?), который полностью меняет ключ в моей логике. Бросьте мне обратную связь.


* Предполагая, что Foo не является подтипом Bar, конечно.

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

возможно,

Ответ 2

Javascript не поддерживает его из коробки, но легко смоделировать желаемую семантику. Если у вас есть базовый "класс", который вы хотите быть абстрактным, поместите метод (ы), который является (являются) абстрактными на нем, и попросите их выбросить ошибку. Если пользователь расширяет ваш "класс" и не обеспечивает реализацию, ошибка будет выбрана. Например, вы можете сделать

function Thing() {...}
Thing.prototype.abstractMethod = function() {
    throw 'You must implement abstractMethod';
}