paginas - ¿Tiene JavaScript el tipo de interfaz(como la ''interfaz'' de Java)?
javascript pdf (10)
Interfaces JavaScript:
Aunque JavaScript no tiene el tipo de interface
, 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 asegurar interfaces consistentes entre 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 quedan sin atender. Muchas veces, el enfoque más robusto es demasiado engorroso y obstaculiza al implementador (desarrollador).
Este es un enfoque de Interfaces / Clases abstractas que no es muy engorroso, es explicativo, mantiene las implementaciones dentro de las Abstracciones al mínimo y deja suficiente espacio para metodologías dinámicas o personalizadas:
function resolvePrecept(interfaceName) {
var interfaceName = interfaceName;
return function curry(value) {
/* throw new Error(interfaceName + '' requires an implementation for ...''); */
console.warn(''%s requires an implementation for ...'', interfaceName);
return value;
};
}
var iAbstractClass = function AbstractClass() {
var defaultTo = resolvePrecept(''iAbstractClass'');
this.datum1 = this.datum1 || defaultTo(new Number());
this.datum2 = this.datum2 || defaultTo(new String());
this.method1 = this.method1 || defaultTo(new Function(''return new Boolean();''));
this.method2 = this.method2 || defaultTo(new Function(''return new Object();''));
};
var ConcreteImplementation = function ConcreteImplementation() {
this.datum1 = 1;
this.datum2 = ''str'';
this.method1 = function method1() {
return true;
};
this.method2 = function method2() {
return {};
};
//Applies Interface (Implement iAbstractClass Interface)
iAbstractClass.apply(this); // .call / .apply after precept definitions
};
Participantes
Resolver Precepto
La función resolvePrecept
es una función de utilidad y ayuda que se utiliza dentro de su Clase abstracta . Su trabajo es permitir el manejo personalizado de la implementación de los preceptos encapsulados (datos y comportamiento) . Puede lanzar errores o advertir y asignar un valor predeterminado a la clase Implementor.
iAbstractClass
El iAbstractClass
define la interfaz a 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 precepto . 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 la aplica mediante el uso de Constructor-Hijacking : iAbstractClass.apply(this)
. Al definir los datos y el comportamiento de arriba, y luego secuestrar el constructor de la Interfaz, pasando el contexto del Implementador al constructor de la Interfaz, podemos asegurarnos de que se agregarán las anulaciones del Implementador y que la Interfaz explicará las advertencias y los valores predeterminados.
Este es un enfoque muy sencillo que me ha servido muy bien a mi equipo y a mí en el transcurso del tiempo y los diferentes proyectos. Sin embargo, tiene algunas advertencias y desventajas.
Inconvenientes
Aunque esto ayuda a implementar la consistencia en todo su software en un grado significativo, no implementa interfaces verdaderas , sino que las emula. Aunque se explican las definiciones, los valores predeterminados y las advertencias o errores, la explicación del uso es impuesta y afirmada por el desarrollador (como ocurre con 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:
- Afirmaciones de tipos de retorno.
- Afirmaciones de firmas.
- Congelar objetos de acciones de
delete
- Afirmaciones de cualquier otra cosa prevaleciente o necesaria en la especificidad de la comunidad de JavaScript
Dicho esto, espero que esto te ayude tanto como lo tiene mi equipo y yo.
Estoy aprendiendo a hacer OOP con JavaScript . ¿Tiene el concepto de interfaz (como la interface
de Java)?
Así que sería capaz de crear un oyente ...
Cuando desee utilizar un transcompiler, entonces puede probar TypeScript. Admite características preliminares de ECMA similares a las que hacen los lenguajes coffeescript o babel.
En TypeScript su interfaz puede verse como:
interface IMyInterface {
id: number; // TypeScript types are lowercase
name: string;
callback: (key: string; value: any; array: string[]) => void;
type: "test" | "notATest"; // so called "union type"
}
Lo que no puedes hacer:
- Definir patrones RegExp para valor de tipo
- Definir validación como longitud de cadena
- Rangos de números
- etc.
Espero que a quien todavía esté buscando una respuesta le resulte útil.
Puede probar con un Proxy (es estándar desde ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
latLngLiteral = new Proxy({},{
set: function(obj, prop, val) {
//only these two properties can be set
if([''lng'',''lat''].indexOf(prop) == -1) {
throw new ReferenceError(''Key must be "lat" or "lng"!'');
}
//the dec format only accepts numbers
if(typeof val !== ''number'') {
throw new TypeError(''Value must be numeric'');
}
//latitude is in range between 0 and 90
if(prop == ''lat'' && !(0 < val && val < 90)) {
throw new RangeError(''Position is out of range!'');
}
//longitude is in range between 0 and 180
else if(prop == ''lng'' && !(0 < val && val < 180)) {
throw new RangeError(''Position is out of range!'');
}
obj[prop] = val;
return true;
}
});
Entonces puedes decir fácilmente:
myMap = {}
myMap.position = latLngLiteral;
JavaScript (edición ECMAScript 3) tiene una palabra reservada para implements
guardada para uso futuro . Sin embargo, creo que esto está destinado exactamente para este propósito, en un apuro por obtener la especificación por la puerta, no tuvieron tiempo para definir qué hacer con ella, por lo que, en el momento actual, los navegadores no hacen nada más. déjelo allí y, a veces, quejarse si intenta usarlo para algo.
Es posible y, de hecho, lo suficientemente fácil como para crear su propio Object.implement(Interface)
con una lógica que se confunde cuando un conjunto particular de propiedades / funciones no se implementa en un objeto determinado.
Escribí un artículo sobre object-orientation a object-orientation donde uso mi propia notación de la siguiente manera :
// Create a ''Dog'' class that inherits from ''Animal''
// and implements the ''Mammal'' interface
var Dog = Object.extend(Animal, {
constructor: function(name) {
Dog.superClass.call(this, name);
},
bark: function() {
alert(''woof'');
}
}).implement(Mammal);
Hay muchas formas de proteger a este gato en particular, pero esta es la lógica que usé 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 ''implementado'' al Function.prototype
de Function.prototype
que algunas personas pueden tener un problema, pero creo que funciona muy bien.
Function.prototype.implement = function() {
// Loop through each interface passed in and then check
// that its members are implemented in the context object (this).
for(var i = 0; i < arguments.length; i++) {
// .. Check member''s logic ..
}
// Remember to return the class being tested
return this;
}
Javascript no tiene interfaces. Pero se puede escribir en pato, se puede encontrar un ejemplo aquí:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
Necesita interfaces en Java ya que está tipificado de forma estática y el contrato entre clases debe conocerse durante la compilación. En JavaScript es diferente. JavaScript se escribe dinámicamente; significa que cuando obtiene el objeto, simplemente puede verificar si tiene un método específico y llamarlo.
No hay noción de "esta clase debe tener estas funciones" (es decir, no hay interfaces per se), porque:
- La herencia de JavaScript se basa en objetos, no en clases. Eso no es un gran problema hasta que te das cuenta:
- JavaScript es un lenguaje de tipo extremadamente dinámico: puede crear un objeto con los métodos adecuados, lo que haría que se ajuste a la interfaz, y luego anular la definición de todas las cosas que lo hicieron compatible . Sería tan fácil subvertir el sistema de tipos, ¡incluso accidentalmente! - que en primer lugar no valdría la pena intentar crear un sistema de tipos.
En su lugar, JavaScript utiliza lo que se llama escritura de pato . (Si camina como un pato, y grazna como un pato, en lo que a JS le importa, es un pato.) Si su objeto tiene los métodos quack (), walk () y fly (), el código puede usarlo donde lo desee. un objeto que puede caminar, quackear y volar, sin requerir la implementación de alguna interfaz "Duckable". La interfaz es exactamente el conjunto de funciones que utiliza el código (y los valores de retorno de esas funciones), y con la escritura de pato, se obtiene de forma gratuita.
Ahora, eso no quiere decir que su código no fallará a la mitad, si intenta llamar a some_dog.quack()
; obtendrá un TypeError. Francamente, si le estás diciendo a los perros que curten, tienes problemas un poco más grandes; la tipificación de patos funciona mejor cuando se mantienen todos los patos en fila, por así decirlo, y no se permite que los perros y los patos se mezclen a menos que los esté tratando como animales genéricos. En otras palabras, aunque la interfaz es fluida, sigue ahí; Por lo general, es un error pasar un perro al código que espera que baje y vuele en primer lugar.
Pero si estás seguro de que estás haciendo lo correcto, puedes solucionar el problema del perro curandero probando la existencia de un método en particular antes de intentar usarlo. Algo como
if (typeof(someObject.quack) == "function")
{
// This thing can quack
}
Por lo tanto, puede verificar todos los métodos que puede usar antes de usarlos. Sin embargo, la sintaxis es algo fea. Hay una manera un poco más bonita:
Object.prototype.can = function(methodName)
{
return ((typeof this[methodName]) == "function");
};
if (someObject.can("quack"))
{
someObject.quack();
}
Esto 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, casi cualquier otro navegador que no sea IE 6-8), hay incluso una manera de evitar que la propiedad aparezca en for...in
:
Object.defineProperty(Object.prototype, ''can'', {
enumerable: false,
value: function(method) {
return (typeof this[method] === ''function'');
}
}
El problema es que los objetos de IE7 no tienen .defineProperty
en absoluto, y en IE8, supuestamente solo funciona en objetos de host (es decir, elementos de 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 algunos estilos de codificación suponen que todo el mundo escribe un código incorrecto y prohíbe modificar el Object.prototype
de Object.prototype
en caso de que alguien quiera usar a ciegas for...in
. Si le importa eso, o está usando un código (IMO roto ) que lo hace, intente con una versión ligeramente diferente:
function can(obj, methodName)
{
return ((typeof obj[methodName]) == "function");
}
if (can(someObject, "quack"))
{
someObject.quack();
}
Recoge una copia de '' patrones de diseño de JavaScript '' de Dustin Díaz . Hay algunos capítulos dedicados a implementar interfaces de JavaScript a través de Duck Typing. Es una buena lectura también. Pero no, no hay un lenguaje nativo de implementación de una interfaz, tienes que Duck Type .
// example duck typing method
var hasMethods = function(obj /*, method list as strings */){
var i = 1, methodName;
while((methodName = arguments[i++])){
if(typeof obj[methodName] != ''function'') {
return false;
}
}
return true;
}
// in your code
if(hasMethods(obj, ''quak'', ''flapWings'',''waggle'')) {
// IT''S A DUCK, do your duck thang
}
Sé que este es uno antiguo, pero recientemente me he dado cuenta de que necesito más y más para tener una API útil para verificar los objetos en comparación con las interfaces. Así que 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'')
.
Esperemos que alguien lo encuentre útil.
También hay jQuery.isFunction (método), si prefieres que sea el código de cHao.