Необходимы ли интерфейсы в JavaScript?
Я полагаю, это может применяться к любому динамическому языку, но тот, который я использую, - JavaScript. У нас есть ситуация, когда мы пишем пару элементов управления в JavaScript, которые должны предоставить функцию Send (), которая затем вызывается страницей, на которой размещен JavaScript. У нас есть массив объектов, у которых эта функция отправки определена, поэтому мы перебираем коллекцию и вызываем Send() для каждого из объектов.
на языке OO, если вы хотите сделать что-то подобное, вы имейте интерфейс IControl, который имеет функцию Send (), которая должна быть реализована каждым элементом управления, а затем у вас будет коллекция реализаций IControl, которые вы будете перебирать и вызывать метод send.
мой вопрос в том, что JavaScript является динамическим языком, есть ли необходимость определять интерфейс, который должны наследовать элементы управления, или достаточно просто вызвать функцию Send (), представленную на элементах управления?
5 ответов
динамические языки часто поощряют Утиной Типизацией, в которых методы объекта диктуют, как его следует использовать, а не явный контракт (например, интерфейс).
поскольку вы можете вызвать любой метод на любом объекте на динамическом языке, я не уверен, как интерфейсы вступят в игру каким-либо действительно полезным способом. Нет контрактов для принудительного исполнения, потому что все определяется во время вызова - объект может даже изменить, соответствует ли он "контракту" в течение его жизни, поскольку методы добавляются и удаляются во время выполнения. Вызов завершится ошибкой, если объект не выполняет контракт, или завершится ошибкой, если он не реализует участника - в любом случае то же самое для большинства практических целей.
это то же самое для PHP; вам действительно не нужны интерфейсы. Но они существуют для архитектурных нужд. В PHP вы можете указать подсказки типа для функций, которые могут быть полезны.
во-вторых, интерфейс-это контракт. Это официальный контракт, который все объекты из этого интерфейса имеют эти функции. Лучше убедиться, что ваши классы соответствуют этим требованиям, чем помнить:"мм, этот класс isEnabled()
но другой checkIfEnabled()
". Межфазные границы помочь вам стандартизировать. Другие, работающие с производным объектом, не должны проверять, является ли имя isEnabled
или checkIfEnabled
(лучше пусть интерпретатор поймает эти проблемы).
мы видели хорошую реализацию на странице ниже, это наша (короткая версия)
var Interface = function (methods) {
var self = this;
self.methods = [];
for (var i = 0, len = methods.length; i < len; i++) {
self.methods.push(methods[i]);
}
this.implementedBy = function (object) {
for (var j = 0, methodsLen = self.methods.length; j < methodsLen; j++) {
var method = self.methods[j];
if (!object[method] || typeof object[method] !== 'function') {
return false;
}
}
return true;
}
};
//Call
var IWorkflow = new Interface(['start', 'getSteps', 'end']);
if (IWorkflow.implementedBy(currentWorkFlow)) {
currentWorkFlow.start(model);
}
весь пример в: http://www.javascriptbank.com/how-implement-interfaces-in-javascript.html
другая альтернатива интерфейсам предлагается Боб.js:
1. Проверьте, реализован ли интерфейс:
var iFace = { say: function () { }, write: function () { } };
var obj1 = { say: function() { }, write: function () { }, read: function () { } };
var obj2 = { say: function () { }, read: function () { } };
console.log('1: ' + bob.obj.canExtractInterface(obj1, iFace));
console.log('2: ' + bob.obj.canExtractInterface(obj2, iFace));
// Output:
// 1: true
// 2: false
2. Извлеките интерфейс из объекта и все равно выполните функции правильно:
var obj = {
msgCount: 0,
say: function (msg) { console.log(++this.msgCount + ': ' + msg); },
sum: function (a, b) { console.log(a + b); }
};
var iFace = { say: function () { } };
obj = bob.obj.extractInterface(obj, iFace);
obj.say('Hello!');
obj.say('How is your day?');
obj.say('Good bye!');
// Output:
// 1: Hello!
// 2: How is your day?
// 3: Good bye!