J'apprends à faire de la POO avec JavaScript . At-il le concept d'interface (comme Javainterface
)?
Je pourrais donc créer un auditeur ...
javascript
oop
Tom Brito
la source
la source
Réponses:
Il n'y a aucune notion de "cette classe doit avoir ces fonctions" (c'est-à-dire, aucune interface en soi), car:
Au lieu de cela, JavaScript utilise ce qu'on appelle la frappe de canard . (S'il marche comme un canard et quacks comme un canard, pour JS, c'est un canard.) Si votre objet a les méthodes quack (), walk () et fly (), le code peut l'utiliser où il le souhaite un objet qui peut marcher, charlatan et voler, sans nécessiter la mise en œuvre d'une interface "Duckable". L'interface est exactement l'ensemble des fonctions que le code utilise (et les valeurs de retour de ces fonctions), et avec la frappe de canard, vous obtenez cela gratuitement.
Maintenant, cela ne veut pas dire que votre code n'échouera pas à mi-parcours, si vous essayez d'appeler
some_dog.quack()
; vous obtiendrez une TypeError. Franchement, si vous dites aux chiens de charlatan, vous avez des problèmes légèrement plus importants; la frappe de canard fonctionne mieux lorsque vous gardez tous vos canards dans une rangée, pour ainsi dire, et ne laissez pas les chiens et les canards se mélanger, sauf si vous les traitez comme des animaux génériques. En d'autres termes, même si l'interface est fluide, elle est toujours là; c'est souvent une erreur de passer un chien au code qui s'attend à ce qu'il charlatane et vole en premier lieu.Mais si vous êtes sûr de faire la bonne chose, vous pouvez contourner le problème des chiens charlatans en testant l'existence d'une méthode particulière avant d'essayer de l'utiliser. Quelque chose comme
Vous pouvez donc vérifier toutes les méthodes que vous pouvez utiliser avant de les utiliser. Cependant, la syntaxe est plutôt moche. Il y a une façon un peu plus jolie:
Il s'agit de JavaScript standard, il devrait donc fonctionner dans n'importe quel interpréteur JS utile. Il a l'avantage supplémentaire de lire comme l'anglais.
Pour les navigateurs modernes (c'est-à-dire à peu près n'importe quel navigateur autre que IE 6-8), il existe même un moyen d'empêcher la propriété d'apparaître dans
for...in
:Le problème est que les objets IE7 n'en ont pas
.defineProperty
du tout, et dans IE8, il ne fonctionnerait que sur les objets hôtes (c'est-à-dire les éléments DOM et autres). Si la compatibilité est un problème, vous ne pouvez pas l'utiliser.defineProperty
. (Je ne mentionnerai même pas IE6, car il n'est plus pertinent en dehors de la Chine.)Un autre problème est que certains styles de codage aiment supposer que tout le monde écrit du mauvais code et interdisent de le modifier
Object.prototype
au cas où quelqu'un voudrait l'utiliser aveuglémentfor...in
. Si vous vous souciez de cela ou utilisez du code ( cassé IMO ), essayez une version légèrement différente:la source
for...in
est - et a toujours été - confronté à de tels dangers, et quiconque le fait sans au moins considérer que quelqu'un ajouté àObject.prototype
(une technique pas rare, de l'aveu même de cet article) verra son code casser entre les mains de quelqu'un d'autre.for...in
problème. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…for...in
problème" existera toujours dans une certaine mesure, car il y aura toujours du code bâclé ... enfin, ça, etObject.defineProperty(obj, 'a', {writable: true, enumerable: false, value: 3});
c'est un peu plus de travail que justeobj.a = 3;
. Je peux totalement comprendre les gens qui n'essaient pas de le faire plus souvent. : PRécupérez une copie de ' modèles de conception JavaScript » de Dustin Diaz . Il y a quelques chapitres dédiés à l'implémentation d'interfaces JavaScript via Duck Typing. C'est aussi une bonne lecture. Mais non, il n'y a pas d'implémentation native d'une interface, vous devez utiliser Duck Type .
la source
JavaScript (ECMAScript édition 3) a un
implements
mot réservé enregistré pour une utilisation future . Je pense que cela est destiné exactement à cette fin, cependant, pressés de sortir la spécification, ils n'ont pas eu le temps de définir quoi en faire, donc, à l'heure actuelle, les navigateurs ne font rien d'autre laissez-le reposer là-bas et, de temps à autre, vous plaignez si vous essayez de l'utiliser pour quelque chose.Il est possible et même assez simple de créer le vôtre
Object.implement(Interface)
méthode avec une logique qui recule à chaque fois qu'un ensemble particulier de propriétés / fonctions n'est pas implémenté dans un objet donné.J'ai écrit un article sur l' orientation objet où j'utilise ma propre notation comme suit :
Il existe de nombreuses façons d'habiller ce chat en particulier, mais c'est la logique que j'ai utilisée pour ma propre implémentation d'interface. Je trouve que je préfère cette approche, et elle est facile à lire et à utiliser (comme vous pouvez le voir ci-dessus). Cela signifie ajouter une méthode de mise en œuvre à
Function.prototype
laquelle certaines personnes peuvent avoir un problème, mais je trouve que cela fonctionne à merveille.la source
var interf = arguments[i]; for (prop in interf) { if (this.prototype[prop] === undefined) { throw 'Member [' + prop + '] missing from class definition.'; }}
. Voir le bas du lien de l' article pour un exemple plus élaboré.Interfaces JavaScript:
Bien que JavaScript ne possède pas le
interface
type, il est souvent nécessaire. Pour des raisons liées à la nature dynamique de JavaScript et à l'utilisation de l'héritage prototypique, il est difficile de garantir des interfaces cohérentes entre les classes - cependant, il est possible de le faire; et fréquemment émulé.À ce stade, il existe plusieurs manières particulières d'émuler des interfaces en JavaScript; la variance des approches satisfait généralement certains besoins, tandis que d'autres ne sont pas traités. Souvent, l'approche la plus robuste est trop lourde et contrarie le réalisateur (développeur).
Voici une approche des interfaces / classes abstraites qui n'est pas très lourde, est explicative, réduit au minimum les implémentations à l'intérieur des abstractions et laisse suffisamment de place pour les méthodologies dynamiques ou personnalisées:
Les participants
Résolveur de préceptes
La
resolvePrecept
fonction est une fonction utilitaire et d'assistance à utiliser à l'intérieur de votre classe abstraite . Son travail consiste à permettre une implémentation-gestion personnalisée des préceptes encapsulés (données et comportement) . Il peut générer des erreurs ou avertir - ET - attribuer une valeur par défaut à la classe Implementor.iAbstractClass
Le
iAbstractClass
définit l'interface à utiliser. Son approche implique un accord tacite avec sa classe de mise en œuvre. Cette interface affecte chaque précepte au même espace de noms de précepte exact - OU - à tout ce que renvoie la fonction de résolution de préceptes . Cependant, l'accord tacite se résout en un contexte - une disposition de mise en œuvre.Réalisateur
Le Implementor simplement « d' accord » avec une interface ( iAbstractClass dans ce cas) et l' applique par l'utilisation de Constructor-Détournement :
iAbstractClass.apply(this)
. En définissant les données et le comportement ci-dessus, puis en détournant le constructeur de l'interface - en passant le contexte de l'implémentateur au constructeur de l'interface - nous pouvons nous assurer que les remplacements de l'implémentateur seront ajoutés et que l'interface expliquera les avertissements et les valeurs par défaut.Il s'agit d'une approche très peu encombrante qui a très bien servi mon équipe et moi au fil du temps et des différents projets. Cependant, il a quelques mises en garde et inconvénients.
Désavantages
Bien que cela aide à implémenter la cohérence dans votre logiciel dans une large mesure, il n'implémente pas de véritables interfaces - mais les émule. Bien que les définitions, les valeurs par défaut et les avertissements ou erreurs soient expliqués, l'explication de l'utilisation est appliquée et affirmée par le développeur (comme avec la plupart des développements JavaScript).
Il s'agit apparemment de la meilleure approche pour les "Interfaces en JavaScript" , mais j'aimerais voir les éléments suivants résolus:
delete
actionsCela dit, j'espère que cela vous aidera autant que mon équipe et moi.
la source
Vous avez besoin d'interfaces en Java car il est typé statiquement et le contrat entre les classes doit être connu lors de la compilation. En JavaScript, c'est différent. JavaScript est typé dynamiquement; cela signifie que lorsque vous obtenez l'objet, vous pouvez simplement vérifier s'il a une méthode spécifique et l'appeler.
la source
yourMethod
à l'entrée n ° 5 de laSuperclass
table v, et pour chaque sous-classe qui a la sienneyourMethod
, pointe simplement l'entrée n ° 5 de cette sous-classe à la mise en œuvre appropriée.Implementation
qui implémenteSomeInterface
ne dit pas simplement qu'elle implémente toute l'interface. Il contient des informations indiquant «J'implémenteSomeInterface.yourMethod
» et pointe vers la définition de la méthode pourImplementation.yourMethod
. Lorsque la JVM appelleSomeInterface.yourMethod
, elle recherche dans la classe des informations sur les implémentations de la méthode de cette interface et trouve qu'elle doit appelerImplementation.yourMethod
.J'espère que toute personne qui cherche toujours une réponse la trouvera utile.
Vous pouvez essayer d'utiliser un proxy (c'est standard depuis ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Ensuite, vous pouvez facilement dire:
la source
Lorsque vous souhaitez utiliser un transcompilateur, vous pouvez essayer TypeScript. Il prend en charge les projets de fonctionnalités ECMA (dans la proposition, les interfaces sont appelées " protocoles ") similaires à ce que font des langages comme coffeescript ou babel.
Dans TypeScript, votre interface peut ressembler à:
Ce que vous ne pouvez pas faire:
la source
il n'y a pas d'interfaces natives en JavaScript, il existe plusieurs façons de simuler une interface. j'ai écrit un paquet qui le fait
vous pouvez voir l'implantation ici
la source
Javascript n'a pas d'interfaces. Mais il peut être de type canard, un exemple peut être trouvé ici:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
la source
Je sais que c'est un ancien, mais je me suis récemment rendu compte que j'avais de plus en plus besoin d'une API pratique pour vérifier les objets par rapport aux interfaces. J'ai donc écrit ceci: https://github.com/tomhicks/methodical
Il est également disponible via NPM:
npm install methodical
Il fait essentiellement tout ce qui est suggéré ci-dessus, avec quelques options pour être un peu plus strict, et tout cela sans avoir à faire des charges de passe-
if (typeof x.method === 'function')
partout.J'espère que quelqu'un le trouvera utile.
la source
C'est une vieille question, néanmoins ce sujet ne cesse de me déranger.
Comme bon nombre des réponses ici et sur le Web se concentrent sur «l'application» de l'interface, je voudrais suggérer une autre vue:
Par exemple, j'ai un générateur de courrier électronique qui s'attend à recevoir des usines de sections de courrier électronique , qui "savent" comment générer le contenu et le code HTML des sections. Par conséquent, ils ont tous besoin d'avoir une sorte de
getContent(id)
etgetHtml(content)
méthodes.Le principal défi avec ce modèle est que les méthodes doivent être
static
, ou obtenir comme argument l'instance elle-même, pour accéder à ses propriétés. Cependant, il y a des cas où je trouve que ce compromis en vaut la peine.la source
interface abstraite comme celle-ci
créer une instance:
et l'utiliser
la source