5

Come posso verificare se un oggetto JavaScript è un'implementazione di un'interfaccia utilizzando lo Google Closure inheritance mechanism?Verifica se l'oggetto è l'implementazione dell'interfaccia nel framework delle classi di Google Closure


non ho trovato alcun accenno di my.Animal negli oggetti creati tramite new my.Dog() e object instanceof my.Animal non ha funzionato. Le uniche informazioni sull'interfaccia sono errori del compilatore quando si dimentica di implementare metodi nella classe figlio.

/** 
* @interface 
*/ 
my.Animal = function() {}; 

/** 
* Does something. 
* @return {string} 
*/ 
my.Animal.prototype.doSomething; 

/** 
* @constructor 
* @implements {my.Animal} 
*/ 
my.Dog = function() {}; 

/** @inheritDoc */ 
my.Dog.prototype.doSomething() = function { 
    return "something"; 
} 

var dog = new my.Dog(); 
console.log(dog instanceof my.Animal); // returns false 

Un modo che ho trovato è approssimativamente di prova per la proprietà delle interfacce, anche se questo è male in tanti aspetti:

console.log(!!dog.doSomething); // returns true 
+2

Mi piacerebbe avere un commento su cosa è sbagliato PRIMA di ottenere downvoted. –

risposta

2

@interface è puramente un tipo di controllo di tipo. Nel codice non compilato non c'è nulla che possa ispezionare i commenti per @interface/@implements per aggiungere qualsiasi cablaggio per i controlli di runtime. L'obiettivo di Closure è che il codice eseguirà lo stesso prima e dopo la compilazione (supponendo che si osservi la restrizione per la modalità di ottimizzazione che si sta utilizzando). Lo schema tipico quando si desidera un controllo runtime è di codificare classe che implementa l'interfaccia che ti interessa:

my.Dog.prototype.implements_my_Animal = true; 

poi

if (foo.implements_my_Animal) ... 

Questo è un po 'fastidioso in modo da non lo vedi dove non è necessario Esistono vari modi per eseguire il wrapping ma, se si utilizza la modalità ADVANCED, la maggior parte risulta nella classe di implementazione (my.Dog nel proprio esempio) di escape e non rimovibile se non utilizzata.

+0

Nota: probabilmente dovresti aggiungere un oggetto sentinella invece di vero e controllare l'equivalenza, come '(foo.implements_my_Animal === the_object)' poiché altrimenti otterrai falsi positivi quando un oggetto capita di definire la stessa chiave. Questo può accadere facilmente dopo una compilazione anticipata che la rinomina con qualcosa come "foo.a'. Questo è qualcosa che abbiamo incontrato in Clojurescript: https://dev.clojure.org/jira/browse/CLJS-1658 – ClojureMostly

1

Non è possibile direttamente.

Nel sistema di tipo Closure-compiler, @extends viene utilizzato per l'ereditarietà e correlato ai test instanceof. Implementazioni di interfaccia denotate da @implements sono rigorosamente un controllo del tempo di compilazione. Sono una promessa che il tuo oggetto contiene metodi e proprietà che corrispondono alle definizioni dell'interfaccia.

Come tali, per testarli in fase di esecuzione in modo completo, è necessario verificare l'esistenza e il tipo di ciascuna proprietà dell'interfaccia.