Estou aprendendo a fazer OOP com JavaScript . Possui o conceito de interface (como o Java interface
)?
Então, eu seria capaz de criar um ouvinte ...
javascript
oop
Tom Brito
fonte
fonte
Respostas:
Não há noção de "essa classe deve ter essas funções" (ou seja, nenhuma interface em si), porque:
Em vez disso, o JavaScript usa o que é chamado de digitação de pato . (Se ele anda como um pato e grasna como um pato, na medida em que JS se importa, é um pato.) Se o seu objeto possui métodos quack (), walk () e fly (), o código pode usá-lo onde quer que ele espere um objeto que pode andar, grasnar e voar, sem exigir a implementação de alguma interface "Duckable". A interface é exatamente o conjunto de funções que o código usa (e os valores de retorno dessas funções) e, com a digitação do duck, você obtém isso de graça.
Agora, isso não significa que seu código não falhará no meio, se você tentar ligar
some_dog.quack()
; você receberá um TypeError. Francamente, se você está dizendo para os cães gritarem, você tem problemas um pouco maiores; digitar patos funciona melhor quando você mantém todos os seus patos em ordem, por assim dizer, e não deixa cães e patos se misturarem, a menos que os trate como animais genéricos. Em outras palavras, mesmo que a interface seja fluida, ela ainda está lá; geralmente é um erro passar um cachorro para o código que espera gritar e voar em primeiro lugar.Mas se você tem certeza de que está fazendo a coisa certa, pode solucionar o problema dos cães quacking testando a existência de um método específico antes de tentar usá-lo. Algo como
Portanto, você pode verificar todos os métodos que pode usar antes de usá-los. A sintaxe é meio feia, no entanto. Há uma maneira um pouco mais bonita:
Como o JavaScript é padrão, deve funcionar em qualquer interpretador JS que valha a pena usar. Tem o benefício adicional de ler como o inglês.
Para navegadores modernos (ou seja, praticamente qualquer navegador que não seja o IE 6-8), existe até uma maneira de impedir que a propriedade apareça em
for...in
:O problema é que os objetos do IE7 não possuem
.defineProperty
, e no IE8, ele supostamente funciona apenas em objetos host (ou seja, elementos DOM e outros). Se a compatibilidade for um problema, você não poderá usar.defineProperty
. (Eu nem vou mencionar o IE6, porque é mais irrelevante fora da China.)Outra questão é que alguns estilos de codificação gostam de assumir que todos escrevem códigos incorretos e proíbem a modificação
Object.prototype
caso alguém queira usar cegamentefor...in
. Se você se importa com isso, ou está usando um código (IMO quebrado ), tente uma versão ligeiramente diferente:fonte
for...in
é - e sempre foi - repleto de tais perigos, e qualquer pessoa que faça isso sem pelo menos considerar que alguém adicionado aObject.prototype
(uma técnica não incomum, pela própria admissão desse artigo) verá seu código quebrar nas mãos de outra pessoa.for...in
problema. developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…for...in
problema" ainda existirá até certo ponto, porque sempre haverá código desleixado ... bem, isso eObject.defineProperty(obj, 'a', {writable: true, enumerable: false, value: 3});
é um pouco mais trabalhoso do que apenasobj.a = 3;
. Eu posso entender totalmente as pessoas que não tentam fazer isso com mais frequência. : PPegue uma cópia dos ' JavaScript design patterns ' de Dustin Diaz . Existem alguns capítulos dedicados à implementação de interfaces JavaScript por meio do Duck Typing. É uma boa leitura também. Mas não, não há implementação nativa de linguagem de uma interface, você precisa do Duck Type .
fonte
JavaScript (ECMAScript edição 3) tem uma
implements
palavra reservada salva para uso futuro . Eu acho que isso é planejado exatamente para esse propósito, no entanto, com a pressa de divulgar as especificações, eles não tiveram tempo de definir o que fazer com elas; portanto, atualmente, os navegadores não fazem nada além deixe-o ali e, ocasionalmente, reclame se tentar usá-lo para alguma coisa.É possível e de fato fácil criar seu próprio
Object.implement(Interface)
método com uma lógica que falha sempre que um conjunto específico de propriedades / funções não é implementado em um determinado objeto.Escrevi um artigo sobre orientação a objetos em que use minha própria notação da seguinte maneira :
Existem várias maneiras de tratar desse gato em particular, mas essa é a lógica que usei para minha própria implementação de interface. Acho que prefiro essa abordagem e é fácil de ler e usar (como você pode ver acima). Significa adicionar um método 'implementar' ao
Function.prototype
qual algumas pessoas podem ter problemas, mas acho que funciona lindamente.fonte
var interf = arguments[i]; for (prop in interf) { if (this.prototype[prop] === undefined) { throw 'Member [' + prop + '] missing from class definition.'; }}
. Veja a parte inferior do link do artigo para um exemplo mais elaborado.Interfaces JavaScript:
Embora o JavaScript não tenha esse
interface
tipo, muitas vezes é necessário. Por razões relacionadas à natureza dinâmica do JavaScript e ao uso de herança prototípica, é difícil garantir interfaces consistentes entre as classes - no entanto, é possível fazê-lo; e frequentemente emulado.Neste ponto, existem várias maneiras específicas de emular interfaces em JavaScript; a variação nas abordagens geralmente satisfaz algumas necessidades, enquanto outras não são atendidas. Muitas vezes, a abordagem mais robusta é excessivamente complicada e atrapalha o implementador (desenvolvedor).
Aqui está uma abordagem para interfaces / classes abstratas que não é muito complicada, é explicativa, mantém as implementações dentro de abstrações em um nível mínimo e deixa espaço suficiente para metodologias dinâmicas ou personalizadas:
Participantes
Resolvedor de Preceitos
A
resolvePrecept
função é uma função utilitário e auxiliar para usar dentro da sua Classe Abstrata . Seu trabalho é permitir a manipulação de implementação personalizada de Preceitos encapsulados (dados e comportamento) . Ele pode gerar erros ou avisar - E - atribuir um valor padrão à classe Implementor.iAbstractClass
O
iAbstractClass
define a interface a ser usada. Sua abordagem envolve um acordo tácito com sua classe Implementor. Essa interface atribui cada preceito ao mesmo espaço de nome exato de preceito - OU - para o que a função Resolver do Preceito retornar. No entanto, o acordo tácito resolve para um contexto - uma provisão do Implementador.Implementor
O Implementor simplesmente 'concorda' com uma Interface ( iAbstractClass neste caso) e aplica-lo pelo uso de Construtor-Hijacking :
iAbstractClass.apply(this)
. Ao definir os dados e o comportamento acima e, em seguida, seqüestrar o construtor da Interface - passando o contexto do implementador para o construtor da interface - podemos garantir que as substituições do implementador sejam adicionadas e que a interface explique avisos e valores padrão.Essa é uma abordagem muito incômoda, que serviu muito bem à minha equipe e ao longo do tempo e a diferentes projetos. No entanto, ele tem algumas ressalvas e desvantagens.
Desvantagens
Embora isso ajude a implementar consistentemente todo o software em um grau significativo, ele não implementa interfaces verdadeiras - mas simula-as. Embora as definições, os padrões e os avisos ou erros sejam explicados, a explicação do uso é imposta e afirmada pelo desenvolvedor (como ocorre com grande parte do desenvolvimento do JavaScript).
Essa é aparentemente a melhor abordagem para "Interfaces em JavaScript" , no entanto, eu adoraria ver o seguinte resolvido:
delete
açõesDito isto, espero que isso ajude você tanto quanto a minha equipe e a mim.
fonte
Você precisa de interfaces em Java, pois ele é digitado estaticamente e o contrato entre as classes deve ser conhecido durante a compilação. Em JavaScript é diferente. JavaScript é digitado dinamicamente; significa que, quando você obtém o objeto, pode apenas verificar se ele possui um método específico e chamá-lo.
fonte
yourMethod
a entrada nº 5 naSuperclass
tabela de tabelas e, para cada subclasse que possui sua própriayourMethod
, simplesmente aponta a entrada nº 5 da subclasse. na implementação apropriada.Implementation
que implementaSomeInterface
não apenas diz que implementa toda a interface. Possui informações que dizem "eu implementoSomeInterface.yourMethod
" e aponta para a definição de método paraImplementation.yourMethod
. Quando a JVM chamaSomeInterface.yourMethod
, ela procura na classe informações sobre implementações do método dessa interface e acha que precisa chamarImplementation.yourMethod
.Espero que qualquer pessoa que ainda esteja procurando uma resposta seja útil.
Você pode experimentar usando um Proxy (é padrão desde ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Então você pode facilmente dizer:
fonte
Quando você deseja usar um transcompilador, tente o TypeScript. Ele suporta recursos de rascunho do ECMA (na proposta, as interfaces são chamadas de " protocolos ") semelhantes às linguagens como coffeescript ou babel.
No TypeScript, sua interface pode se parecer com:
O que você não pode fazer:
fonte
não há interfaces nativas no JavaScript, existem várias maneiras de simular uma interface. eu escrevi um pacote que faz isso
você pode ver a implantação aqui
fonte
Javascript não possui interfaces. Mas pode ser do tipo pato, um exemplo pode ser encontrado aqui:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
fonte
Sei que é antigo, mas recentemente me vi precisando cada vez mais de uma API útil para verificar objetos em relação a interfaces. Então eu escrevi isso: https://github.com/tomhicks/methodical
Também está disponível via NPM:
npm install methodical
Basicamente, faz tudo o que foi sugerido acima, com algumas opções para ser um pouco mais rigoroso e tudo sem ter que fazer um monte de
if (typeof x.method === 'function')
clichê.Espero que alguém ache útil.
fonte
Esta é uma pergunta antiga, mas esse tópico nunca deixa de me incomodar.
Como muitas das respostas aqui e em toda a Web se concentram em "impor" a interface, eu gostaria de sugerir uma visão alternativa:
Por exemplo, eu tenho um Gerador de E - mail que espera receber Fábricas de Seções de E-mail , que "sabem" como gerar o conteúdo e o HTML das seções. Assim, eles toda a necessidade de ter algum tipo de
getContent(id)
egetHtml(content)
métodos.O principal desafio desse padrão é que os métodos precisam ser
static
, ou obter como argumento a própria instância, para acessar suas propriedades. No entanto, há casos em que considero essa troca compensadora.fonte
interface abstrata como esta
crie uma instância:
e use
fonte