Estoy aprendiendo a hacer POO con JavaScript . ¿Tiene el concepto de interfaz (como el de Java interface
)?
Entonces podría crear un oyente ...
javascript
oop
Tom Brito
fuente
fuente
Respuestas:
No existe la noción de "esta clase debe tener estas funciones" (es decir, no hay interfaces per se), porque:
En cambio, JavaScript usa lo que se llama escribir pato . (Si camina como un pato y grazna como un pato, por lo que a JS le importa, es un pato). Si su objeto tiene métodos quack (), walk () y fly (), el código puede usarlo donde lo espera un objeto que puede caminar, graznar y volar, sin requerir la implementación de alguna interfaz "Duckable". La interfaz es exactamente el conjunto de funciones que usa el código (y los valores de retorno de esas funciones), y al escribir pato, obtienes eso de forma gratuita.
Ahora, eso no quiere decir que su código no fallará a la mitad, si intenta llamar
some_dog.quack()
; obtendrás un TypeError. Francamente, si le estás diciendo a los perros que graznen, tienes problemas un poco mayores; la escritura de patos funciona mejor cuando mantiene a todos sus patos en fila, por así decirlo, y no permite que los perros y los patos se mezclen a menos que los trate como animales genéricos. En otras palabras, aunque la interfaz es fluida, sigue ahí; a menudo es un error pasar un perro al código que espera que grazne y vuele en primer lugar.Pero si está seguro de que está haciendo lo correcto, puede solucionar el problema del perro graznando probando la existencia de un método en particular antes de intentar usarlo. Algo como
Por lo tanto, puede verificar todos los métodos que puede usar antes de usarlos. Sin embargo, la sintaxis es un poco fea. Hay una forma un poco más bonita:
Este es JavaScript estándar, por lo que debería funcionar en cualquier intérprete JS que valga la pena usar. Tiene el beneficio adicional de leer como el inglés.
Para los navegadores modernos (es decir, prácticamente cualquier navegador que no sea IE 6-8), incluso hay una manera de evitar que la propiedad aparezca en
for...in
:El problema es que los objetos IE7 no tienen
.defineProperty
nada, y en IE8, supuestamente solo funciona en objetos host (es decir, elementos DOM y demás). Si la compatibilidad es un problema, no puede usar.defineProperty
. (Ni siquiera mencionaré IE6, porque ya es bastante irrelevante fuera de China).Otro problema es que a algunos estilos de codificación les gusta suponer que todos escriben códigos incorrectos y prohíben la modificación
Object.prototype
en caso de que alguien quiera usar a ciegasfor...in
. Si le importa eso o está usando un código (IMO roto ) que lo hace, intente con una versión ligeramente diferente:fuente
for...in
está, y siempre ha estado, cargado de tales peligros, y cualquiera que lo haga sin al menos considerar que alguien agregadoObject.prototype
(una técnica no poco común, según la propia admisión de ese artículo) verá su código descifrado en las manos de otra persona.for...in
problema. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…for...in
problema" seguirá existiendo hasta cierto punto, porque siempre habrá un código descuidado ... bueno, eso, yObject.defineProperty(obj, 'a', {writable: true, enumerable: false, value: 3});
es bastante más trabajo que simplementeobj.a = 3;
. Puedo entender totalmente a las personas que no intentan hacerlo con más frecuencia. : PRecoge una copia de ' Patrones de diseño de JavaScript ' de Dustin Diaz . Hay algunos capítulos dedicados a implementar interfaces JavaScript a través de Duck Typing. Es una buena lectura también. Pero no, no hay una implementación nativa del idioma de una interfaz, tienes que Duck Type .
fuente
JavaScript (ECMAScript edición 3) tiene una
implements
palabra reservada guardada para uso futuro . Creo que esto está destinado exactamente para este propósito, sin embargo, en un apuro por sacar la especificación por la puerta, no tuvieron tiempo de definir qué hacer con ella, por lo que, en este momento, los navegadores no hacen nada más déjalo reposar allí y ocasionalmente queja si intentas usarlo para algo.Es posible y de hecho bastante fácil crear su propio
Object.implement(Interface)
método con una lógica que retuerce cuando un conjunto particular de propiedades / funciones no se implementa en un objeto dado.Escribí un artículo sobre orientación a objetos donde uso mi propia notación de la siguiente manera :
Hay muchas formas de crear este gato en particular, pero esta es la lógica que utilicé para mi propia implementación de interfaz. Creo que prefiero este enfoque, y es fácil de leer y usar (como puede ver arriba). Significa agregar un método de "implementación" con el
Function.prototype
que algunas personas pueden tener un problema, pero creo que funciona de maravilla.fuente
var interf = arguments[i]; for (prop in interf) { if (this.prototype[prop] === undefined) { throw 'Member [' + prop + '] missing from class definition.'; }}
. Consulte la parte inferior del enlace del artículo para obtener un ejemplo más elaborado.Interfaces JavaScript:
Aunque JavaScript no tiene el
interface
tipo, a menudo es necesario. Por razones relacionadas con la naturaleza dinámica de JavaScript y el uso de la herencia prototípica, es difícil garantizar interfaces consistentes entre las clases; sin embargo, es posible hacerlo; y frecuentemente emulado.En este punto, hay varias formas particulares de emular interfaces en JavaScript; La variación en los enfoques generalmente satisface algunas necesidades, mientras que otras no se abordan. Muchas veces, el enfoque más robusto es demasiado engorroso y obstaculiza el implementador (desarrollador).
Aquí hay un enfoque de Interfaces / Clases abstractas que no es muy engorroso, es explicativo, mantiene las implementaciones dentro de Abstracciones al mínimo y deja suficiente espacio para metodologías dinámicas o personalizadas:
Participantes
Resolver preceptos
La
resolvePrecept
función es una función de utilidad y ayuda para usar dentro de su clase abstracta . Su trabajo es permitir el manejo personalizado de la implementación de Preceptos encapsulados (datos y comportamiento) . Puede arrojar errores o advertir - Y - asignar un valor predeterminado a la clase Implementador.iAbstractClass
El
iAbstractClass
define la interfaz que se utilizará. Su enfoque implica un acuerdo tácito con su clase Implementor. Esta interfaz asigna cada precepto al mismo espacio de nombres de precepto exacto, O, a lo que devuelva la función de resolución de preceptos . Sin embargo, el acuerdo tácito se resuelve en un contexto : una disposición del Implementador.Implementador
El implementador simplemente 'está de acuerdo' con una interfaz ( iAbstractClass en este caso) y lo aplica por el uso de Constructor-Secuestro :
iAbstractClass.apply(this)
. Al definir los datos y el comportamiento anteriores, y luego secuestrar el constructor de la Interfaz, pasando el contexto del Implementador al constructor de la Interfaz, podemos asegurarnos de que se agreguen las anulaciones del Implementador, y que la Interfaz explicará las advertencias y los valores predeterminados.Este es un enfoque no engorroso que nos ha servido a mi equipo y a mí muy bien durante el transcurso del tiempo y diferentes proyectos. Sin embargo, tiene algunas advertencias y desventajas.
Inconvenientes
Aunque esto ayuda a implementar consistencia en todo su software en un grado significativo, no implementa interfaces verdaderas , sino que las emula. Aunque las definiciones, valores predeterminados, y las advertencias o errores son explicadas, la explicación de su uso se hace cumplir y afirmó por el desarrollador (como en gran parte del desarrollo de JavaScript).
Este es aparentemente el mejor enfoque para "Interfaces en JavaScript" , sin embargo, me encantaría ver lo siguiente resuelto:
delete
accionesDicho esto, espero que esto te ayude tanto como a mi equipo y a mí.
fuente
Necesita interfaces en Java, ya que está estáticamente tipado y el contrato entre clases debe conocerse durante la compilación. En JavaScript es diferente. JavaScript se escribe dinámicamente; significa que cuando obtienes el objeto puedes verificar si tiene un método específico y llamarlo.
fuente
yourMethod
en la entrada # 5 en laSuperclass
tabla v, y para cada subclase que tiene la suyayourMethod
, simplemente señala la entrada de la subclase # 5 en la implementación apropiada.Implementation
que implementaSomeInterface
no solo dice que implementa toda la interfaz. Tiene información que dice "ImplementoSomeInterface.yourMethod
" y apunta a la definición del método paraImplementation.yourMethod
. Cuando la JVM llamaSomeInterface.yourMethod
, busca en la clase información sobre implementaciones del método de esa interfaz, y encuentra que necesita llamarImplementation.yourMethod
.Espero que cualquier persona que todavía esté buscando una respuesta la encuentre útil.
Puede probar usando un Proxy (es estándar desde ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Entonces puedes decir fácilmente:
fuente
Cuando desee utilizar un transcompilador, puede probar TypeScript. Admite características de borrador de ECMA (en la propuesta, las interfaces se denominan " protocolos ") similares a lo que hacen los lenguajes como coffeescript o babel.
En TypeScript, su interfaz puede verse así:
Lo que no puedes hacer:
fuente
no hay interfaces nativas en JavaScript, hay varias formas de simular una interfaz. He escrito un paquete que lo hace
puedes ver la implantación aquí
fuente
Javascript no tiene interfaces. Pero puede ser tipado, un ejemplo se puede encontrar aquí:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
fuente
Sé que este es antiguo, pero recientemente me he encontrado necesitando cada vez más tener una API práctica para verificar objetos en las interfaces. Entonces escribí esto: https://github.com/tomhicks/methodical
También está disponible a través de NPM:
npm install methodical
Básicamente, hace todo lo sugerido anteriormente, con algunas opciones para ser un poco más estricto, y todo sin tener que hacer un montón de
if (typeof x.method === 'function')
repeticiones.Esperemos que alguien lo encuentre útil.
fuente
Esta es una vieja pregunta, sin embargo, este tema nunca deja de molestarme.
Como muchas de las respuestas aquí y en toda la web se centran en "hacer cumplir" la interfaz, me gustaría sugerir una vista alternativa:
Por ejemplo, tengo un Generador de correo electrónico que espera recibir Fábricas de secciones de correo electrónico , que "saben" cómo generar el contenido y HTML de las secciones. Por lo tanto, todos tenemos que tener algún tipo de
getContent(id)
ygetHtml(content)
métodos.El principal desafío con este patrón es que los métodos tienen que ser
static
, o para obtener como argumento la instancia misma, para poder acceder a sus propiedades. Sin embargo, hay casos en los que creo que esta compensación vale la pena.fuente
interfaz abstracta como esta
crear una instancia:
y úsalo
fuente