2009-09-14 17 views
22

Supongo que esto podría aplicarse a cualquier lenguaje dinámico, pero el que estoy usando es JavaScript. Tenemos una situación en la que estamos escribiendo un par de controles en JavaScript que necesitan exponer una función Send() que luego es llamada por la página que aloja el JavaScript. Tenemos una matriz de objetos que tienen esta función de envío definida, por lo que iteramos a través de la colección y llamamos a Send() en cada uno de los objetos.¿Son necesarias las interfaces en JavaScript?

En un lenguaje OO, si quisiera hacer algo similar, tendría una interfaz IControl que tiene una función Send() que debe implementar cada control y luego tendría una colección de implementaciones de IControl que iterarías y llamarías al método de envío.

Mi pregunta es, como JavaScript es un lenguaje dinámico, ¿hay alguna necesidad de definir una interfaz de la que heredarían los controles, o es lo suficientemente buena para simplemente llamar a la función Send() expuesta en los controles?

+4

Me encanta tu gravatar :) – alex

Respuesta

10

Los lenguajes dinámicos a menudo fomentan Duck Typing, en los que los métodos del objeto dictan cómo se debe usar en lugar de un contrato explícito (como una interfaz).

+34

No creo que las interfaces sean en contraste con la tipificación de patos. Todo lo contrario, en realidad. Al declarar una interfaz, puede tener una declaración clara de los métodos que intentará llamar. A menudo he encontrado métodos que aceptan objetos que son, digamos, tipo archivo, sin ninguna indicación clara de lo que debe implementar un objeto similar a un archivo. ¿Leen() y cierran() lo suficiente? ¿También necesito buscar()? ¿Qué pasa con write()? Las interfaces son una manera clara e inequívoca de exponer sus necesidades, y como tales son una gran mejora ** especialmente ** si desea confiar en pato escribiendo – Andrea

+2

Incluso la capacidad de tener interfaces ad-hoc que simplemente declararon qué métodos y miembros parámetro debería tener sería útil. No tiene que ser una interfaz con nombre, solo una restricción de valor. –

4

Dado que puede llamar a cualquier método en cualquier objeto en un lenguaje dinámico, no estoy seguro de cómo las interfaces entrarán en juego de ninguna manera realmente útil. No hay contratos para hacer cumplir porque todo se determina en el momento de la invocación; un objeto incluso podría cambiar si se ajusta a un "contrato" durante su vigencia a medida que se agregan y eliminan métodos durante el tiempo de ejecución. La llamada fallará si el objeto no cumple con un contrato o fallará si no implementa un miembro; cualquier caso es el mismo para la mayoría de los propósitos prácticos.

+0

No es un [Knol] (http://web.archive.org /web/20120416022026/http://knol.google.com/k/programming-to-the-interface-in-javascript-yes-it-can-be-done-er-i-mean-faked #) (yes knol) sobre este tema – bobobobo

3

Esto es lo mismo para PHP; realmente no necesitas interfaces. Pero existen para las necesidades arquitectónicas. En PHP, puede especificar sugerencias de tipo para funciones que pueden ser útiles.

En segundo lugar, una interfaz es un contrato. Es un contrato formal que todos los objetos de esta interfaz tienen esas funciones. Es mejor asegurarse de que sus clases cumplan con esos requisitos que recordar: "mm, esta clase tiene isEnabled() pero la otra es checkIfEnabled()". Las interfaces te ayudan a estandarizar. Otros que trabajan en el objeto derivado no tienen que verificar si el nombre es isEnabled o checkIfEnabled (es mejor dejar que el intérprete capte esos problemas).

2

Vimos una buena aplicación en la página más adelante, esta es nuestra (versión corta de la misma)

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); 
} 

La totalidad ejemplo se encuentra en: http://www.javascriptbank.com/how-implement-interfaces-in-javascript.html

0

Otra alternativa a las interfaces es ofrecido por bob.js:

1. Comprobar si se implementa la interfaz:

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. interfaz Extracto del objeto y todavía ejecutar las funciones correctamente:

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! 
Cuestiones relacionadas