Я учусь делать ООП с помощью JavaScript . Есть ли у него концепция интерфейса (например, Java interface
)?
Так что я бы смог создать слушателя ...
javascript
oop
Том Брито
источник
источник
Ответы:
Там нет понятия "этот класс должен иметь эти функции" (то есть, интерфейсы как таковые), потому что:
Вместо этого в JavaScript используется так называемая « утиная печать» . (Если он ходит как утка и крякает как утка, то, что касается JS, это утка.) Если ваш объект имеет методы quack (), walk () и fly (), код может использовать его везде, где он ожидает объект, который может ходить, крякать и летать, не требуя реализации какого-либо "Duckable" интерфейса. Интерфейс - это в точности набор функций, которые использует код (и возвращаемые значения из этих функций), и с помощью утки вы получаете это бесплатно.
Это не значит, что ваш код не потерпит неудачу на полпути, если вы попытаетесь позвонить
some_dog.quack()
; вы получите TypeError. Честно говоря, если вы говорите собакам крякать, у вас есть немного большие проблемы; Печатание утки работает лучше всего, когда вы, так сказать, держите всех своих уток в ряд и не позволяете собакам и уткам смешиваться, если вы не относитесь к ним как к обычным животным. Другими словами, несмотря на то, что интерфейс плавный, он все еще там; часто бывает ошибкой передавать собаку в код, который ожидает, что она сначала будет крякать и летать.Но если вы уверены, что поступаете правильно, вы можете обойти проблему собаководства, проверив наличие конкретного метода, прежде чем пытаться его использовать. Что-то вроде
Таким образом, вы можете проверить все методы, которые вы можете использовать, прежде чем использовать их. Синтаксис довольно уродливый, хотя. Есть немного более красивый способ:
Это стандартный JavaScript, поэтому он должен работать в любом интерпретаторе JS, который стоит использовать. Это имеет дополнительное преимущество чтения как английский.
Для современных браузеров (то есть практически любого браузера, кроме IE 6-8), есть даже способ, чтобы свойство не отображалось в
for...in
:Проблема заключается в том, что у объектов IE7 нет
.defineProperty
вообще, а в IE8 он предположительно работает только с хост-объектами (то есть с элементами DOM и т. Д.). Если совместимость является проблемой, вы не можете использовать.defineProperty
. (Я даже не буду упоминать IE6, потому что он больше не имеет значения за пределами Китая.)Другая проблема заключается в том, что некоторым стилям кодирования нравится предполагать, что каждый пишет плохой код, и запрещать модификацию
Object.prototype
в случае, если кто-то хочет использовать вслепуюfor...in
. Если вы заботитесь об этом или используете (IMO сломанный ) код, который делает, попробуйте немного другую версию:источник
for...in
это - и всегда было - чревато такими опасностями, и любой, кто делает это, по крайней мере, не считая, что кто-то добавилObject.prototype
(что весьма необычно, по собственному признанию этой статьи), увидит, как его код сломается в чужих руках.for...in
проблемы. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…for...in
проблема» все еще будет существовать в некоторой степени, потому что всегда будет неаккуратный код ... ну, это, иObject.defineProperty(obj, 'a', {writable: true, enumerable: false, value: 3});
это немного больше работы, чем простоobj.a = 3;
. Я могу полностью понять людей, которые не пытаются делать это чаще. : PВозьмите копию « Шаблоны дизайна JavaScript » Дастина Диаса . Есть несколько глав, посвященных реализации интерфейсов JavaScript через Duck Typing. Это тоже приятно читать. Но нет, языковой реализации интерфейса не существует, вы должны использовать Duck Type .
источник
В JavaScript (ECMAScript edition 3)
implements
зарезервированное слово сохранено для будущего использования . Я думаю, что это предназначено именно для этой цели, однако, в спешке, чтобы вывести спецификацию за дверь, у них не было времени, чтобы определить, что с ней делать, поэтому в настоящее время браузеры ничего не делают, кроме пусть он сидит там и иногда жалуется, если вы пытаетесь использовать его для чего-то.Возможно и действительно достаточно просто создать свой собственный
Object.implement(Interface)
метод с логикой, которая искажает всякий раз, когда определенный набор свойств / функций не реализован в данном объекте.Я написал статью об объектной ориентации, в которой использую мою собственную запись следующим образом :
Есть много способов обшить эту конкретную кошку, но эту логику я использовал для собственной реализации интерфейса. Я считаю, что предпочитаю этот подход, и его легко читать и использовать (как вы можете видеть выше). Это означает добавление метода «внедрить», с
Function.prototype
которым у некоторых людей могут возникнуть проблемы, но я считаю, что он прекрасно работает.источник
var interf = arguments[i]; for (prop in interf) { if (this.prototype[prop] === undefined) { throw 'Member [' + prop + '] missing from class definition.'; }}
. Смотрите в нижней части статьи ссылку для более подробного примера.Интерфейсы JavaScript:
Хотя JavaScript это не имеет
interface
тип, это зачастую необходимо. По причинам, связанным с динамической природой JavaScript и использованием Prototypical-Inheritance, трудно обеспечить согласованные интерфейсы между классами - однако это возможно; и часто подражать.На данный момент есть несколько конкретных способов эмулировать интерфейсы в JavaScript; Разница в подходах обычно удовлетворяет некоторые потребности, в то время как другие остаются без внимания. Часто самый надежный подход слишком громоздок и мешает разработчику (разработчику).
Вот подход к интерфейсам / абстрактным классам, который не очень громоздок, объясняет, сводит к минимуму реализации внутри абстракций и оставляет достаточно места для динамических или пользовательских методологий:
участники
Завет Резолвер
Эта
resolvePrecept
функция является вспомогательной и вспомогательной функцией для использования внутри вашего абстрактного класса . Его работа заключается в том, чтобы обеспечить настраиваемую обработку реализации инкапсулированных Предписаний (данных и поведения) . Он может выдавать ошибки или предупреждать - И - назначать значение по умолчанию для класса Implementor.iAbstractClass
iAbstractClass
Определяет интерфейс , который будет использоваться. Его подход влечет за собой молчаливое соглашение с его классом Implementor. Этот интерфейс назначает каждую заповедь одному и тому же пространству имен точных заповедей - ИЛИ - любому, что возвращает функция Rescept Resolver . Однако молчаливое соглашение разрешает контекст - положение исполнителя.Implementor
Implementor просто «согласен» с интерфейсом ( iAbstractClass в данном случае) и применяет его с помощью Конструктора-Угон :
iAbstractClass.apply(this)
. Определив данные и поведение выше, а затем перехватив конструктор интерфейса - передав контекст реализатора конструктору интерфейса - мы можем гарантировать, что переопределения реализатора будут добавлены и что интерфейс будет объяснять предупреждения и значения по умолчанию.Это очень не обременительный подход, который послужил моей команде и мне очень хорошо в течение времени и различных проектов. Тем не менее, у него есть некоторые предостережения и недостатки.
Недостатки
Хотя это в значительной степени помогает обеспечить согласованность всего программного обеспечения, оно не реализует настоящие интерфейсы, а имитирует их. Хотя определения, по умолчанию, и предупреждения или ошибки являются пояснено, экспликация использования в исполнение и утверждается застройщиком (как и большая часть развития JavaScript).
Это, казалось бы, лучший подход к «Интерфейсам в JavaScript» , однако мне бы хотелось, чтобы было решено следующее:
delete
действийТем не менее, я надеюсь, что это поможет вам так же, как и моя команда и я.
источник
Вам нужны интерфейсы в Java, так как он статически типизирован и контракт между классами должен быть известен во время компиляции. В JavaScript это отличается. JavaScript динамически типизируется; это означает, что когда вы получаете объект, вы можете просто проверить, есть ли у него определенный метод, и вызвать его.
источник
yourMethod
в запись № 5 вSuperclass
таблице vtable, а для каждого подкласса, который имеет свой собственныйyourMethod
, просто указывает запись этого подкласса № 5. при соответствующей реализации.Implementation
который реализуетSomeInterface
, не просто говорит, что он реализует весь интерфейс. В нем есть информация, которая говорит «Я реализуюSomeInterface.yourMethod
» и указывает на определение метода дляImplementation.yourMethod
. Когда JVM вызываетSomeInterface.yourMethod
, он ищет в классе информацию о реализациях метода этого интерфейса и находит, что ему нужно вызватьImplementation.yourMethod
.Надеюсь, что любой, кто все еще ищет ответ, найдет его полезным.
Вы можете попробовать использовать прокси (это стандартно с ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Тогда вы можете легко сказать:
источник
Если вы хотите использовать транскомпилятор, вы можете попробовать TypeScript. Он поддерживает черновые функции ECMA (в предложении интерфейсы называются « протоколы »), аналогичные тем, которые используются в таких языках, как coffeescript или babel.
В TypeScript ваш интерфейс может выглядеть так:
Что вы не можете сделать:
источник
в JavaScript нет нативных интерфейсов, есть несколько способов симулировать интерфейс. я написал пакет, который делает это
вы можете увидеть имплантацию здесь
источник
Javascript не имеет интерфейсов. Но это может быть напечатано уткой, пример можно найти здесь:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
источник
Я знаю, что это старый, но в последнее время я все больше и больше нуждался в удобном API для проверки объектов по интерфейсам. Поэтому я написал это: https://github.com/tomhicks/methodical
Это также доступно через NPM:
npm install methodical
Он в основном делает все, что предложено выше, с некоторыми вариантами, чтобы быть немного более строгим, и все без необходимости
if (typeof x.method === 'function')
загружать шаблон.Надеюсь, кто-то найдет это полезным.
источник
Это старый вопрос, тем не менее эта тема не перестает меня беспокоить.
Поскольку многие ответы здесь и в Интернете направлены на «усиление» интерфейса, я хотел бы предложить альтернативное представление:
Например, у меня есть Генератор электронной почты, который ожидает получать фабрики разделов электронной почты , которые «знают», как генерировать содержимое разделов и HTML. Следовательно, все они должны иметь какие-то
getContent(id)
иgetHtml(content)
методы.Основная проблема с этим шаблоном заключается в том, что методы должны быть
static
или получить в качестве аргумента сам экземпляр, чтобы получить доступ к его свойствам. Однако есть случаи, в которых я считаю, что этот компромисс стоит хлопот.источник
абстрактный интерфейс, как это
создать экземпляр:
и использовать это
источник