Archive for category OOP
OOP em Javascript – Classes Abstratas
Publicado por javiani em Boas práticas, Design Pattern, Javascript, OOP em junho 19, 2011
E aí galera!
Tenho andado bastante atarefado no trabalho, o que contribui para minha falta aqui no blog, estou muito mais no momento de resolver problemas rapidamente do que de refletir, tenho sentido falta disso.
Mas para não deixar o blog tão abandonado resolvi retomar os posts sobre orientação à objetos em Javascript, porque eu acho muito interessante a forma como resolvemos os problemas nessa linguagem.
Então, vamos lá. O que seria uma Classe abstrata no nosso desenvolvimento? A grosso modo é uma classe com propriedades e/ou métodos como qualquer outra, porém é uma classe que não faz sentido existir por si própria, ou seja, não faz sentido haver uma instância desta classe.
Essa classe serve apenas como base para outras classes que irão herdar seu comportamento, suas características.
Um exemplo, se tivessemos que criar um carro, sabemos que este tem o comportamento de se deslocar, um carro acelera, desacelera e consequentemente altera sua velocidade. Então todo Carro que se preze tem uma velocidade, pode acelerar, pode desacelerar até o momento em que sua velocidade for zero.
Então poderiamos criar esta classe Carro:
var Carro = {
Class :function(){
//Private
var velocidade = 0
//Public
this.acelerar = function(n){
velocidade = velocidade + (n || 1)
}
this.frear = function(n){
velocidade = velocidade - (n || 1)
}
this.velocidade = function(){ return velocidade }
}
}
Esta classe vai funcionar direitinho como planejamos, vai frear, vai acelerar e tem uma propriedade velocidade, privada, que será alterada a cada ação que fizemos.
Porém na perspectiva do paradigma OO a forma como criamos a classe Carro está equivocada. Ela está engessada com métodos e propriedades que não poderiam ser reaproveitados em outras classes de mesmo propósito. Ou melhor poderíam, mas de forma completamente errada.
Veja, se quiséssemos criar uma Moto, com esta classe Carro já implementada, haveria duas formas erradas de se criá-la.
Uma é duplicar a classe Carro e chamar de Moto. ( Se você fizer isso você não vai pro céu )
Outra seria herdar de Carro as propriedades e métodos. ( Se você fizer isso você não só não vai pro céu como vai direto pro inferno )
Duplicar está fora de cogitação, orientação à objetos serve justamente para reaproveitarmos código.
Herdar de Carro é um erro de arquitetura sério, como pode uma Moto ser um Carro ? Não pode.
O jeito de resolver esse problema é criar uma classe base, que seja comum entre os dois objetos e estes dois objetos devem herdar desta classe.
A solução é criar uma classe chamada Veiculo. Bom, um carro é um veículo e uma moto é um veículo, ambos tem o comportamento de um veículo que é de se movimentar, acelerar, frear, alterar sua velocidade.
Beleza, então essa classe Veiculo já resolveria nosso problema, mas esta classe não é uma classe como a Moto ou o Carro. Ela é uma classe que serve apenas para ser herdada, não faz sentido existir uma instância dela, não existe um veículo por si só, veículo é uma designação que damos para um determinado objeto, no nosso caso um carro ou uma moto. Você pode dizer que vai pegar um veículo, ou vai guiar um veículo, mas este veículo no nosso mini-mundo ou é um Carro ou é uma Moto.
Então a classe Veiculo é uma classe abstrata.
Em linguagens mais fortemente tipadas como C++, Java, C# é possível através da própria linguagem definir que uma classe não deve existir por si só, não deve existir uma instância dela e que ela deve ser apenas herdada. No Javascript não é possível definir se uma classe é abstrata apenas usando uma palavra-chave, então, para arquitetar uma solução de classes onde usamos classes abstratas e queremos disciplinar outros programadores para que usem nosso código corretamente, precisamos usar um outro tipo de técnica.
Existem várias técnicas na internet, e essa é a vantagem do Javascript dada sua flexibilidade. Vou mostrar a forma como eu faço, e que eu prefiro fazer. Isto fica aqui entre nós, desenvolvedores de Interface, programadores Javascript, porque se aparecer qualquer programador back-end, desktop, engenheiro de software, vai querer nos matar, porque vamos ferir o conceito de Interfaces, novamente.
Falei em um post passado, sobre como usar Interfaces em Javascript, mas uma interface que é mais um mixin do que uma interface. Mas para nós, programadores Javascript, é uma Interface mais malemolente. Lembrem-se de que uma Interface não deve especificar como se implementa, apenas o que se implementa, porém no Javascript ela vai dizer também como se implementa. Se não viu o post sobre interfaces, eu aconselho que veja para entender o que estou falando. =)
Tá, mas por que estou falando tanto de Interfaces se nosso problema é como forçar que uma classe seja abstrata ?
Porque vamos resolver esse problema justamente usando uma “Interface“.
Como ? Olha só:
var Interface = {
abstract :function(c){
if( c.prototype.isPrototypeOf(this) )
throw new Error('Abstract Class')
}
}
Criei ali uma Interface que possui uma implementação para um tipo abstrato de classe. Existe um método abstract que vai receber um construtor e vai dizer se a classe é abstrata, perguntando se o protótipo do escopo atual é o mesmo protótipo do construtor. Em outras palavras, se somos uma instância daquele construtor então lançamos um erro.
Então, para criarmos todos os nossos veículos usaríamos a Interface para criarmos a classe abstrata Veiculo e herdaríamos Veiculo em Carro e Moto:
var Veiculo = {
Class :function(velocidade){
Interface.abstract.apply(this, [Veiculo.Class])
this.acelerar = function(n){
velocidade = velocidade + (n || 1)
}
this.frear = function(n){
velocidade = velocidade - (n || 1)
}
this.velocidade = function(){ return velocidade }
}
}
var Carro = {
Class :function(){
Veiculo.Class.apply(this, [0])
// Implementações de um carro
}
}
var Moto = {
Class :function(){
Veiculo.Class.apply(this, [0])
// Implementações de uma moto
}
}
var carro = new Carro.Class
carro.acelerar(20)
carro.velocidade() // 20
var moto = new Moto.Class
moto.acelerar()
moto.velocidade() // 1
**Perceba que eu passei Veiculo.Class para a Interface.abstract além de passar 0 como a velocidade inicial.
É claro que aqui estamos com duas classes idênticas Moto e Carro, porém suas classes seriam preenchidas com métodos e propriedades específicas dos seus tipos posteriormente.
É isso, os puritanos e estudiosos do paradigma orientado à objetos tentariam mandar me matar ao ver que usei Interface para criar uma classe abstrata, mas fica aqui entre nós
.
Aproveite e tente rodar na sua máquina estas classes, veja o que acontece quando se tenta criar uma instância de Veiculo. =)
Um grande abraço.
Design Pattern Observer em Javascript
Publicado por javiani em Design Pattern, Javascript, OOP, Técnicas de programação em maio 22, 2010
E aí galerinha do mal, é nóis again.
É engraçado que sempre ao se começar um post eu fico horas só pensando na saudação rsrss. É difícil inovar.. mas ainda que seja repetitivo é melhor que aquele “Bom dia” que alguns colocam né ? Caray, quem garante que a criatura que vai ler, estará lendo de manhã ? =/
Deixando de lado as viadagens, vamos ao que nos interessa de verdade que é Javascript na veia irmão.
Saber sobre os Design Patterns e onde aplicar é o que diferencia os programadores homens dos programadores meninos. Às vezes não é tão trivial identificar qual design pattern usar para um determinado problema e não é possível saber todos decor.
E é por isso que estou postando bastante sobre esse assunto, para termos uma referência na nossa linguagem sobre isso.
Então, o que é um Observer e quando usar ?
Tá de pé? Então senta.
O padrão Observer é um padrão do tipo comportamental, no qual um objeto chamado “Subject” contém uma lista de dependentes, chamados Observers. Os Subjects então notificam para esta lista de Observers automaticamente quando algum estado modifica, geralmente chamando um de seus métodos.
É geralmente usado para implementar sistemas distribuidos com delegação de eventos.
Fonte: Wikipédia
Este padrão usa alguns conceitos de outros design patterns, como Interfaces e Visitor. Lembram que eu falei pra estudar bastante sobre Interfaces pois todos os outros design patterns utilizam este conceito ? Este padrão utiliza interfaces e utiliza também uma idéia do padrão Visitor que se chama inversão de métodos. O Visitor não é pré-requisito para entender o Observer, mas é interessante saber que muitos design patterns utilizam conceitos de outros para se compor.
Basicamente é isso, quando temos um objeto que ao ser alterado uma propriedade dele, outros objetos precisam saber que este objeto foi alterado e precisam invocar um método deles assim que isso acontecer.
Em Javascript o Observer pode ser amplamente usado, porque lidamos com eventos mais do que qualquer coisa em Javascript.
É bastante necessário por exemplo, quando temos uma tela que é dinâmica a nível de Js, com paginação e tal. Quando por exemplo vamos para a próxima página da paginação, criamos novos elementos de acordo com novos dados e estes elementos perdem todos os eventos que os outros tinham na página anterior. Temos que ficar atualizando os eventos dos objetos quando nossa tela é alterada. O Pattern Observer pra isso é uma mão na roda.
Mas eu vou dar um exemplo bem simples, talvez não muito usual, mas para ser facilmente fixado e absorvido por vocês meus caros leitores.
Primeiro, nosso diagrama de classes do Pattern.
![]()
Agora nosso problema.
Temos dois objetos, Tela e Ponto, onde o objeto Tela será responsável por mostrar o objeto Ponto na tela. Porém o objeto Ponto tem um estado, que é a posição dele na tela, ele tem um atributo x e um atributo y que são suas coordenadas.
Sempre que eu alterar uma das suas coordenadas ( x ou y ) o objeto Tela precisa saber que isso aconteceu e atualizar sua posição na tela.
Portanto, vamos resolver esse problema usando o Pattern Observer.
Como o objeto Tela precisará observar o objeto Ponto, então será este nosso Observer. Então Ponto será nosso Subject.
Usando nosso “Javiani way” de construir Classes, o padrão Observer é construido da seguinte maneira:
var Interface = {
Observer : function(){
this.update = function(o){
throw new Error('Implemente Observer.update()')
}
},
Subject : function(){
var observers = {}
this.add_observer = function(o){ observers[o] = o }
this.rem_observer = function(o){ delete observers[o] }
this.notify = function(){
for(var x in observers)
observers[x].update(this)
}
}
}
Lembrando que Observer e Subject são interfaces, não classes. Portanto, teremos duas classes, Tela e Ponto, na qual cada uma delas IMPLEMENTARÁ um tipo de interface.
A interface acima Observer, terá um método obrigatório, que será o update, que fará alguma coisa com o objeto passado como argumento para o método. Este método será chamado pelo objeto Subject, notificando o Observer que um estado do Subject foi alterado.
A interface Subject, terá uma lista contendo todos os observers que um objeto Subject terá. E também terá 3 métodos. Um para adicionar um observer à lista, outro pra remover um observer da lista, e outro para passear sobre a lista e avisar à todos os seus Observers registrados que alguma coisa foi alterada, chamando o método update dos Observers passando o objeto que foi alterado. No nosso caso este objeto seria um objeto do tipo Ponto.
Vamos as classes Tela e Ponto então.
Classe ponto com um setter/getter para os pontos x e y. Ela implementará a interface Subject e notificará aos seus Observers que este ponto foi alterado no momento em que for setado um valor novo para x ou para y:
var Ponto = {
Class : function(){
Interface.Subject.apply( this )
var x = 0;
var y = 0;
this.x = function(i){
if(i){
x = i
this.notify()
}
else return x
}
this.y = function(i){
if(i){
y = i
this.notify()
}
else return y
}
},
New : function(){ return new this.Class() }
}
Agora a Classe Tela, que implementará Interface.Observer, terá um método update obrigatório que será chamado pelo Subject, mandando o subject como argumento.
var Tela = {
Class : function(object){
Interface.Observer.apply(this)
var html = object
this.desenha = function(o){
this.desenha[o.constructor].apply(this, arguments)
}
this.desenha[ Ponto.Class ] = function(o){
html.style.left = o.x() + 'px'
html.style.top = o.y() + 'px'
}
this.update = function(o){ this.desenha(o) }
},
New : function(object){ return new this.Class(object) }
}
Chamando um pouco a atenção à forma como montei a Tela, primeiro implementei a interface Observer, o construtor da classe Tela recebe como parâmetro um objeto html e o guarda numa variável privada. Esta classe tem um método sobrecarregado this.desenha. Por que imagino que este objeto Tela não desenhará apenas um ponto mas outros elementos futuramente. ( Se não conhece esta forma de overload, veja o artigo anterior à este )
Então o método sobrecarregado desenha que recebe um ponto, apenas definirá a posição em pixel, no atributo Css left, e top considerando que este objeto html esteja em posição absoluta ou relativa.
O método update será chamado pelo objeto Ponto assim que se alterar qualquer uma das suas coordenadas, isso será feito pelo método notify.
Pronto, agora vamos instanciar os objetos e fazer o padrão Observer funcionar:
window.onload = function(){
var dot = document.getElementById('dot')
var tela = Tela.New(dot) // Ou new Tela.Class(dot)
var ponto = Ponto.New() // Ou new Ponto.Class
ponto.add_observer(tela)
ponto.x(490)
ponto.y(80)
}
Aí está, pegamos um elemento html na tela, o passamos como argumento para o construtor de Tela e instanciamos o objeto tela.
Logo depois disso instanciamos o objeto ponto, adicionamos um observer à ele, que será o objeto tela.
Assim que setarmos um novo valor para x ou para y, o método notify em ponto será chamado, este fará uma chamada do método update de todos os observers registrados passando o objeto ponto como argumento.
O objeto tela ao ser notificado que houve uma alteração em ponto, desenhará na tela a nova posição do ponto. =)
Sacaram ?
Deixei disponível um exemplo deste código, abram-o no firefox de preferência, e setem um novo valor para o ponto, para x ou para y, ou para os dois no console. Deixei públicos os objetos tela e ponto.
Ahh, para não perder o costume de Cientista, aqui vai uma funçãozinha pra fazer o ponto animado =)
var t = 0.0
var fx = function(x, r, t){ return (x + r*Math.cos(t/2)) }
var fy = function(x, r, t){ return (x + r*Math.sin(t/2)) }
setInterval(function(){
if( t == 12 ) t = 0
ponto.x( fx(screen.width/2, 40, t) )
ponto.y( fy(screen.height/2 - 180, 40, t) )
t+=.5
}, 100)
Só colar no firebug e executar =D.
Um grande abraço galera, valeu!
Overload em Javascript
Publicado por javiani em Design Pattern, Idéias, Javascript, OOP, Técnicas de programação em abril 17, 2010
E ae gente, é nóis de novo =).
Eu queria falar desta vez sobre a técnica conhecida como overloading ou sobrecarga de métodos mas em javascript. Sabemos que a linguagem até a versão 1.5 não oferece isso por padrão mas oferece uma série de coisas que nos ajudam a contornar essa falta.
O que seria uma sobrecarga ou um overloading? Em Ciência da Computação, overloading é uma “feature” da linguagem que nos permite criar uma série de métodos de mesmo nome mas que se diferem uma das outras pelo número de parâmetros, pelo tipo dos parâmetros ou pelo seu retorno, ou os três ao mesmo tempo.
Se você quisesse fazer um método setter e getter, você estaria extremamente inclinado à fazer isso:
string getNome(){ return nome; }
void setNome(string n){ nome = n }
Não há nada errado no código acima, mas não estaríamos usando as técnicas de programação OO se fizessemos isso. Um problema que vejo nessa implementação é que sua aplicação tende a ficar com muitos métodos de nomes diferentes, aumentando consideravelmente a curva de aprendizado de um programador terceiro que pretende usar esse código. Ao invés de ter que aprender 10 nomes de métodos, o programador teria de aprender 20, utilizando como base o esquema feito acima.
Uma maneira elegante então seria algo do tipo:
string nome(){ return Nome; }
void nome(string n){ Nome = n; }
Desta forma você só precisaria conhecer o método “nome”. Se você não passar nada ele te retorna o nome. Se você passar alguma coisa, significa que você está querendo “setar” o nome.
Em C++ e Java é possível fazer o que fiz acima sem maiores preocupações. A própria linguagem oferece esse recurso para que possa sobrecarregar os métodos.
Mas e em Javascript ?
Eu já vi várias e excelentes implementações de sobrecarga em vários blogs brasileiros e gringos, mas o que me incomodava nessas implementações é que sempre usavam algum iterador para resolver o problema. Sempre tinha um “for” ali ou algo do tipo. Seguindo a mesma filosofia dos outros posts, pretendo usar um método de sobrecarga que utilize os próprios recursos da linguagem, assim como fiz com Herança e Classes em um post mais antigo.
Como fazer?
Sabemos que o compilador ou interpretador precisa diferenciar os métodos de mesmo nome de duas formas. Primeiro a quantidade de parâmetros que passamos para a função. A segunda é pelo tipo de parâmetro que passamos.
Eu escolhi neste método usar um ou outro, não misturar os dois ao mesmo tempo porque até agora nunca precisei usar este tipo de sobrecarga em Javascript, então é código escrito sem necessidade. Então mãos a massa.
Sobrecarga – Número de parâmetros
Mais uma vez vou utilizar o método “apply” do Js para resolver essa questão, como a linguagem mexe muito com prototipos e construtores, nada mais inteligente do que usar esse método de escopo. A idéia que tive foi usar uma função como uma função e ao mesmo tempo como um objeto que segura suas próprias propriedades.
var Person = {
Class: function(){
//Private
var name = ''
//Public
this.name = function(){
return this.name[ arguments.length ].apply( this, arguments )
}
this.name[0] = function(){ return name }
this.name[1] = function(n){ name = n }
this.name[2] = function(a, b){ name = a + " " + b }
}
}
Aqui eu crio uma função ( método ) com nome “name” e crio mais 3 propriedades dela que são: 0, 1 e 2. São números, mas ainda sim são propriedades do método name. O que a função principal vai fazer é ver quantos parâmetros ela tem e vai chamar a sua propriedade correspondente, que nada mais é que outro método que vai ser executado no mesmo contexto que a name e terá os mesmos parâmetros que a name.
Logo:
var Edu = new Person.Class
Edu .name() // ''
Edu .name('Eduardo')
Edu . name() // "Eduardo"
Edu . name('Eduardo', 'Ottaviani')
Edu . name() // "Eduardo Ottaviani"
Não é porque eu tive essa idéia não, mas eu considero esta a forma mais elegante de sobrecarga de operadores até agora. Talvez não seja a mais eficiente, não testei sua velocidade em relação as outras técnicas. Se for mais lenta, creio que não seja perceptível.
Mas e na hora de sobrecarregar a função através do tipo do parâmetro passado? Como fazer?
Sobrecarga – Tipo de parâmetro
Bom, os métodos existentes até agora consistem em checar o objeto através do typeof, então faz-se um switch onde caso o objeto seja uma string faz uma coisa, se for número faz outra etc.
Há duas formas de saber o que é um objeto, uma é usar o typeof que considero ruim.
Ruim porque ela não retorna exatamente o que deseja. Um caso clássico é dar um typeof []. Retornaria um “object”. Um array é um objeto mas não é apenas um objeto, ele é um objeto do tipo Array.
A outra forma é olhar seu construtor. Esta sim é uma excelente forma de se saber qual o tipo de um objeto. Por que? Porque Javascript define os construtores como as “Classes” dos objetos, portanto uma string é definida por um construtor String, um número é definido por um construtor Number e assim por diante. Em javascript, é o construtor que define o tipo do objeto.
Quando você entende isso, você entende tudo sobre a mecânica da linguagem Javascript, e percebe que há muito mais tipos na linguagem do que pensava.
Por exemplo: (Ruim)
typeof new Date() // object typeof new Person.Class // object typeof [] // object
Exemplo : ( Bom )
new Date().constructor == Date // true var edu = new Person.Class; edu.constructor == Person.Class // true [].constructor == Array // true
Viram? é o construtor que define o tipo do objeto, então mesmo o Person.Class é um tipo, e pode ser definido como o tipo “Person.Class” e não um object.
Dada essa explanação sobre os tipos, como eu faria para implementar um overload de tipos ?
Desta forma:
var Person = {
Class: function(){
this.type = function(){
return this.type[
arguments[0].constructor
].apply(this, arguments)
}
this.type[String] = function(){
alert('String')
}
this.type[RegExp] = function(){
alert('Regex')
}
this.type[Person.Class] = function(){
alert("Person")
}
}
}
A lógica aqui é a mesma da lógica de sobrecarga por quantidade de argumento, só que desta vez eu armazeno no método type outros métodos como propriedades e crio uma relação de tipo entre eles.
Ao executar o método type() passando um objeto como parâmetro, essa função tentará chamar uma propriedade com o valor de construtor igual ao do objeto do parâmetro. Achando esta propriedade, ela será executada no mesmo contexto e usando os mesmos argumentos que a função type mãe.
O interessante é que você acaba descobrindo que há muito mais tipos de objetos no Js, porque usando o typeof você não consegue diferenciar todos eles.
Olha só:
var Edu = new Person.Class
Edu . type ("Eduardo") // alert - "String"
Edu . type (/Eduardo/) // alert - "Regexp"
Edu . type (Edu) // alert - "Person"
Eu poderia também sobrecarregar para um outro método que reconheça uma Date(), usando o mesmo princípio dos outros métodos.
É possível ainda chamar os métodos de tipo ou número diretamente, sem precisar chamar o pai:
Edu . type[RegExp]() Edu . name[2](a, b)
Sinceramente eu prefiro mil vezes usar os recursos da própria linguagem à usar uma função a parte que itere sobre os objetos, faça comparações ou coisas do tipo. Eu estudei alguns tipos de sobrecarga de blogs gringos, caso vocês não tenham gostado da minha forma, eu recomendo usar esses outros métodos de sobrecarga:
John Resig (jQuery) : http://ejohn.org/blog/javascript-method-overloading/
http://webreflection.blogspot.com/2010/02/javascript-overload-patterns.html
É isso galera. Até o próximo post. Comentários são muito bem vindos.
Aqueleabrassss
OOP em Javascript – Interfaces
Publicado por javiani em Design Pattern, Idéias, Javascript, OOP, Técnicas de programação em março 7, 2010
Olá galera do javaspirit!
Hoje eu gostaria de compartilhar uma idéia que tive
para implementação de interfaces em Javascript, já que nosso foco agora é o reuso de código e fácil manutenção temos que pensar sempre na forma de Orientação à objetos.
Peço desculpas pelo post longo, mas eu preferi aumentá-lo um pouco porque interface é um conceito um pouco estranho e difícil de se entender e acho que vale a pena colocar pelo menos o desenvolvimento de um exemplo prático no final.
A Interface é uma forma de desacoplar a implementação da classe, ela provê uma forma de especificar que métodos um objeto deve ter.
Teóricamente é possível implementar interfaces em todas ou na maioria esmagadora das linguagens de programação, mas nem todas implementam uma palavra-chave ou uma estrutura definida para a utilização de interfaces. É o caso de Javascript, então como implementá-la?
O princípio primário da orientação à objetos diz que devemos programar para a interface e não para implementação. Rigidamente, a interface deve dizer quais métodos uma classe deve implementar.
Em Java, a interface tem esta cara:
public interface Motor {
void acelerar();
void frear();
}
Ou seja, definimos uma interface Motor, onde freia ou acelera.
Cumprindo o que prometi nos últimos posts, irei usar os mesmos exemplos para fixar as idéias de maneira mais fácil.
Recapitulando, tinhamos uma classe Carro e uma Classe Motocicleta que herdavam da classe abstrata Veiculo. Lembram?
Voltando à Interface em Java, se quisessemos que a classe Carro implementasse a interface Motor, faríamos:
public class Carro implements Motor{}
Deu pra notar que as interfaces não dizem como deve ser implementado, mas o que deve ser implementado. Esta classe Carro, precisaria obrigatóriamente implementar os métodos acelerar e frear.
Eu sinceramente não gosto de seguir sempre 100% às regras porque acredito que não há uma solução que sirva para todos os casos. Javascript tem uma notação diferente da maioria das linguagens, é um linguagem única, então tentar emular as interfaces de maneira que funcione como o Java por exemplo, pra mim é um erro. Javascript é extremamente flexível em grande parte por ser fracamente tipada, usar Interfaces é de certa forma forçar um comportamento de tipagem forte reduzindo a grande qualidade de javascript que é a sua flexibilidade.
Já vi algumas implementações de interfaces em javascript e todas tentavam copiar essa estrutura de java, contendo loops para verificar se a classe implementava os métodos e etc.
Eu particularmente acho todas ruins.
Bom, vou então mostrar como implemento as Interfaces em javascript e para isso vou precisar quebrar uma regra definida para interfaces. Peço então que abram um pouco suas mentes, porque seguir cegamente um conceito é restringir também sua criatividade.
1ª “As interfaces dizem o que deve ser implementado e não dizer como deve ser implementado”
Em javascript essa regra é inútil. Conseguimos passar os escopos, temos todo o potencial de programação funcional, podemos então definir um método que se aplica a qualquer classe que o implemente, se não se aplicar, o sobrecarregamos.
Então uma forma que vejo de implementar Interface de forma elegante copiando a estrutura de Java seria:
var Interface = {
motor : function(name){
this.frear = function(){
throw "Implemente o método frear na Classe " + name
}
this.acelerar = function(){
throw "Implemente o método acelerar na Classe " + name
}
}
}
Então, implementando esta interface na nossa classe Carro:
var Carro = {
Class: function(){
Interface.motor.apply(this, ["Carro"])
var velocidade = 0
this.velocidade = function(){
return velocidade
}
}
}
Vejam que usei de novo o método apply, como fiz nas heranças no post passado. Ou seja, de forma semântica digo: “Interface motor se aplique à isso”. Vejam que a estrutura da Interface é muito similar a de Classes, não teve curva de aprendizado aqui, vocês já sabem como herdar os atributos se viram o post passado =).
Passei um argumento ["Carro"] como segundo parâmetro do método apply, porque montei os métodos da interface motor de forma a apresentar erros indicando onde precisaria implementar os métodos.
**O método apply precisa que os parâmetros da função chamada seja um array. Se preferir, poderia usar o “call” ao invés, então poderia passar “Carro” apenas como uma simples string.
Se eu fizesse então:
var carro = new Carro.Class
carro . acelerar()
Geraria uma excessão, avisando que eu devo implementar o método acelerar na classe Carro. Na verdade o método está implementado, porém de forma a forçar o programador Js a sobrescrevê-lo.
Agora eu vou mostrar um exemplo de uso de interfaces do dia-a-dia, mostrando um uso para uma situação real. Eu estou de fato negligênciando a regra número um de interfaces, pois farei uma interface que não só vai obrigar a classe a ter certos métodos, como vou implementar estes métodos na própria interface. Come on!!!!
INTERFACES NA PRÁTICA
Vou criar uma classe para fazer o mascaramento de campos do tipo “text” em um formulário. E vou guardar nessa classe um objeto estático, chamado Methods, que armazenará o nome e as funções que farão as máscaras em formato json.
var Maskarade = {
Class : function( fields ){
for(var x in fields)
document.getElementById(x).onkeydown = function(){
var self = this
setTimeout(function(){
self.value =
Maskarade.Methods[ fields[x] ]( self.value )
},100)
}
},
Methods : {
digits_only: function(v){ return v.replace(/\D/g, '') },
letters_only: function(v){ return v.replace(/\d/g, '') }
}
}
Vou instanciá-la, tenho um form com um input com id igual à “number1″:
new Maskarade.Class({
'number1' : 'digits_only'
})
Ao instanciar o construtor da classe vai percorrer o json passado como argumento, e para cada chave do json (que é o id do campo) eu vou “setar” o keydown deste campo e vou mascarar conforme a mascara do valor do json. É uma classe super simples.
Beleza, funciona perfeitamente. O código está correto, sem falhas. Mas eu quero que essa classe funcione com o jQuery, porque não quero fazer uma instância com muitos parâmetros, se meu site tivesse 300 campos a serem mascarados da mesma forma teria de botar 300 campos na instancia da classe, e porque meu chefe gosta de jQuery =).
Bom, não é uma boa embutir código jQuery ali na classe Maskarade, isso seria um erro. Nem seria interessante verificar se existe um jQuery e fazer um if onde caso contrário usa o jeito sem jQuery, pelo amor de Deus isso seria quase que matar uma criança recém nascida com 19 facadas no peito.
Estão entendendo onde a Interface entra? Conseguem visualizar uma forma de usá-la ali na classe? Vou dar uma força:
var Interface = {
jQuery : function(){
this.$ = jQuery
this.keydown = function(el, f){
el.keydown(f)
}
},
Standard : function(){
this.$ = function(el){
return document.getElementById(el)
}
this.keydown = function(el, f){
el.onkeydown = f
}
}
}
Olhaaaaaaaaaaaaaa

Vejam, eu tenho duas preocupações, a primeira é pegar o elemento, a segunda é dar um evento à ele. Logo, eu criei uma interface que vai ter dois métodos, um pega o elemento, o outro dá o evento de keypress neste elemento.
Então ali na interface tem um jeito padrão que vai pegar o elemento pelo id pelo método this.$.
E vai dar um evento à um elemento através do método this.keydown.
E tem o jeito jQuery de fazer as coisas. Apenas criei um apelido para referenciar jQuery através do nome this.$.
E criei um método que recebe um elemento e uma função e dá um keypress a lá jQuery way =).
Como fica a classe então abstraindo as formas de se pegar os elementos e adicionar um evento à eles?
Assim:
var Maskarade = {
Class : function( fields ){
Interface.Standard.apply(this)
for(var x in fields)
this.keydown( this.$(x), function(){
var self = this
setTimeout(function(){
self.value =
Maskarade.Methods[ fields[x] ]( self.value )
},100)
})
},
Methods: {
digits_only: function(v){ return v.replace(/\D/g, '') },
letters_only: function(v){ return v.replace(/\d/g, '') }
}
}
Olha ali a chamada da interface Standard na Classe viram? Eu poderia também passar para o construtor da classe a interface e fazer uma lazy instance, criando um objeto que poderia usar jQuery ou não =). Depende do que planeja para o seu projeto.
this.$ vai pegar o elemento, e this.keydown vai receber o elemento, uma função e atrelar esta função ao evento deste elemento.
E daria para desacoplar ainda mais coisas dessa classe. Se eu tiver uma outra classe que faz a validações, então eu poderia usar os métodos digits_only e letters_only também não poderia ? Oras, vamos botar esse Methods para fora da classe e botá-lo dentro da Interface:
var Interface = {
jQuery : function(){
this.$ = jQuery
this.keydown = function(el, f){
el.keydown(f)
}
},
Standard : function(){
this.$ = function(el){
return document.getElementById(el)
}
this.keydown = function(el, f){
el.onkeydown = f
}
},
Methods: {
digits_only: function(v){ return v.replace(/\D/g, '') },
letters_only: function(v){ return v.replace(/\d/g, '') }
}
}
var Maskarade = {
Class : function( fields ){
Interface.Standard.apply(this)
for(var x in fields)
this.keydown( this.$(x), function(){
var self = this
setTimeout(function(){
self.value =
Maskarade.Methods[ fields[x] ]( self.value )
},100)
})
},
Methods: Interface.Methods
}
Beleza, agora sim.
Se eu implementasse então a interface jQuery na classe, poderia usar uma classe nos elementos html e botar mascaras em todos eles com uma chamada bem enxuta:
new Maskarade.Class({ '.numbers' : 'digits_only' })
\o/ YEAAAH!
Perceberam que a interface obrigou a utilização dos métodos e ainda definiu a sua implementação, quebrando completamente a regra número um das interfaces. Mas para que seguir à risca um conceito que em javascript não se encaixa muito bem?
Ás vezes acho que devemos deixar nossa intuição e criatividade nos guiar para resolver qualquer problema independente do paradigma da linguagem, é muito importante conhecer bem a linguagem que programa e usar conceitos existentes como inspiração e não seguí-las totalmente e cegamente. Neste caso, mostrei um exemplo onde o interessante é ter a implementação na própria interface.
Como a interface não passa de um singleton no js, você pode determinar o namespace que quiser para armazenar de forma semântica seus métodos. Eu não quis dificultar muito, então usei um namespace curto, Interface.nome_do_metodo.
Para quem acompanha meus posts e gosta, eu aconselho à ler e reler a minha implementação caso não tenham entendido, porque muitos dos Design Patterns existentes e que planejo falar mais pra frente utilizam o conceito de Interfaces.
E aí? gostaram? não gostaram? Comentem então =).
Um grande abraço.
OOP em javascript – Herança e Singleton pattern
Publicado por javiani em Boas práticas, Design Pattern, Javascript, OOP, Técnicas de programação em janeiro 24, 2010
Olá CAMAGADAS!
Iniciados em classes em javascript, gostaria de falar um pouco sobre as técnicas que utilizo para herdar classes e falar um pouco sobre dois métodos para implementar singletons.
Primeiro, a herança. Não quero esticar muito sobre esse assunto e imagino que saibam pelo menos para que serve isso. Se alguém não sabe, em algum daqueles links que passei no post anterior à esse deve ter. Senão aqui vai uma breve explicação:
A Herança é um princípio da Programação Orientada a Objetos que permite que as classes compartilhem atributos e operações baseados em um relacionamento, geralmente generalização. A herança permite a criação de subclasses que herdam alguns dos atributos e das operações (ou Métodos) da classe pai (super-classe ou classe base). A herança é um conceito aplicado no momento de criação das classes. Ela é usada na intenção de reaproveitar código ou comportamento generalizado ou especializar operações ou atributos.
fonte: Wikipédia
Herança
A idéia de Classe é gerar um template, um tipo de alguma coisa que queremos criar. A instância é nada mais que um objeto concretizado deste tipo. Vou utilizar um exemplo clássico e simples de se abstrair, vou tentar usar sempre os mesmos exemplos nos posts de Orientação à objetos em javascript.
Vamos criar um objeto Moto, e um objeto Carro. Os dois aceleram, fream e tem velocidade. Os dois fazem mais ou menos a mesma coisa, mas não são A MESMA COISA.
Podemos pensar que os dois são veículos. Então temos uma classe em comum, a classe Veiculo =).
var Veiculo = {
Class : function(){
var velocidade = 0
this.acelerar = function(){ velocidade += 10}
this.frear = function(){ velocidade -=10 }
this.velocidade = function(){ return velocidade }
}
}
Criamos então uma Classe em comum aos dois objetos, Moto e Carro. Como fazer a herança para os dois? Simples:
Moto:
var Motocicleta = {
Class : function(){
Veiculo.Class.apply(this)
}
}
Carro:
var Carro = {
Class : function(){
Veiculo.Class.apply(this)
}
}
var moto = new Motocicleta.Class() moto . acelerar() moto . velocidade() // 10
function Page(){
var width = 800;
this.getWidth = function(){
return width;
}
}
Page.instance = null;
Page.getInstance = function(){
if (Page.instance == null) Page.instance = new Page();
return Page.instance;
}
var Deus = {
Class : function(){
var self = this
Deus.getInstance = function(){ return self }
delete Deus.Class
},
getInstance : function(){ return new Deus.Class }
}
var Singleton = {}
var Projeto = {
version : '1.0',
sidebar : function(){},
util : {
Analitics : function(){}
}
}
Projeto.util.Analitics()
Mais: Milfont.org/tech – Herança no Javascript