OOP em javascript – Herança e Singleton pattern

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:

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)
		
	}
}
Então:
var moto = new Motocicleta.Class()
	moto . acelerar()
	moto . velocidade() // 10
Olha que chupetinha..
Isso vale também para a instancia de carro. Ambas as classes herdam os métodos da classe mãe Veiculo.  Não existe apenas esta forma de se implementar a herança em javascript, mas eu considero essa a mais elegante de todas, e acho inclusive semântica. Porque em inglês, está praticamente dizendo :  “Classe Veiculo! Aplique-se à isto”.
O apply é um método herdado para todos os tipos Function. Ele te da o poder de chamar qualquer função determinando qual será o escopo e os parâmetros passados.
Quando chamamos Veiculo.Class.apply(this) nas duas classes, estamos chamando a função Veiculo.Class de dentro das Classes usando o próprio escopo delas. Ou seja, no momento em que a Veiculo.Class estiver sendo executada, quando chegar nas linhas this.acelerar,, this.etc,  ela vai saber que this se refere ao escopo da própria classe, portanto vai setar os valores para o escopo da classe Moto e Carro.
A variável privada velocidade é passada para o escopo das classes filhas graças ao Closure, porque a função Veiculo.Class inicia uma variável livre que pode ser vista através dos métodos públicos this.acelerar, this.frear e this.velocidade e por usar a palavra chave var a cada chamada da função Veiculo.Class se criará uma nova variável privada “velocidade”, uma para cada classe.
Design Pattern : Singleton
Algumas vezes precisamos de um objeto único que terá seus estados e métodos únicos e de maneira estática. Ou seja, queremos que haja apenas uma e somente única instancia daquele objeto.
Vi muitas implementações na internet de singleton em js, e todas eram péssimas. Se forem procurar, vão achar em sites brasileiros ou gringos muitas implementações parecidas com essa:
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;
}
A primeira impressão é de que é uma boa implementação de singleton, porque segue um padrão semântico bem próximo aos usados em linguagens como o Java e C++.
Mas é uma abordagem péssima para javascript. Em javascript você não consegue definir constantes como em java por exemplo quando usa a palavra-chave final. Então, no caso acima, Page.instance pode ser a qualquer momento modificada para null e aí vc terá duas instâncias Singleton.
Eu particularmente uso dois tipos de singleton, um desenvolvi por conta própria e o outro é puramente usar o que a linguagem tem.
Se por algum motivo precisa fazer uma classe dinâmica Singleton, usando construtores, a forma que eu pensei foi essa:
var Deus = {
	Class : function(){
		var self = this
				
		Deus.getInstance = function(){ return self }
		delete Deus.Class
	},
	getInstance : function(){ return new Deus.Class	}
}
Digamos que Deus exista e que haja apenas um. A funcionalidade da Classe Deus está toda encapsulada em Deus.Class e a classe tem também um método estático getInstance. A minha idéia foi a seguinte:
Existem dois jeitos de instanciar Deus. Uma chamando new Deus.Class e a outra Deus.getInstance().
No primeiro, a função Deus.Class é envocada salva o escopo em uma variável, redefine o método estatico getInstance para que retorne o escopo salvo self e por fim, deleta a variável Deus.Class do objeto Deus. Pronto! você não consegue mais instanciar Deus.Class, porque essa variável não existe mais. Pode apenas recuperar o objeto através de Deus.getInstance.
No segundo, ao chamar Deus.getInstance sem usar o new,  ele retorna uma nova instancia da classe o que levará ao nosso primeiro caso acima.
De uma forma ou outra, sempre terá apenas uma instancia do objeto.
Essa maneira de criar Singletons não é muito comum. Pra falar a verdade até agora não precisei usá-la. Ela ainda pode ser burlada, mas não é tão fácil quanto setar uma variável, de forma que consegue disciplinar de maneira mais eficaz o programador que irá por ventura fazer a  manutenção do código.
E finalmente o modo mais simples mais perfeito mais fácil de se criar um Singleton.
var Singleton = {}
É meus caros… Singleton a grosso modo não é uma instância única de um objeto ? Então… A notação json do javascript nos permite criar um objeto dinamicamente de forma bem elegante, onde podemos criar propriedades e métodos estáticos para armazenar e/ou modificar os estados desse objeto.
Simples!
Você com certeza já deve ter usado um Singleton sem saber. Geralmente o povo usa os Singletons para formar namespaces em um objeto encapsulado. Por exemplo:
var Projeto = {
	version : '1.0',
	sidebar : function(){},
	util : {
		Analitics : function(){}
	}
}
	
Projeto.util.Analitics()
Eu não tinha tanta liberdade para usar Javascript Orientado à Objetos em outras empresas que trabalhei. Mas nessa atual ( F.biz)  tenho uma liberdade muito grande para mexer com orientação a objetos em javascript e tenho percebido que isso ajuda e MUITO no desenvolvimento, tanto na produtividade quanto na manutenção e por incrível que pareça no desempenho. Sem contar que fica mais divertido =).
O javascript evolui sempre e a cada dia que passa novas idéias e inovações aparecem.
Coisas que antes não eram viáveis devido à restrições de hardware, hoje já podem ser feitas sem comprometer o processamento da máquina. Funcionalidades que antes eram feitas em server-side, hoje podem ser feitas via client sem problemas, aliviando o tráfego e melhorando ainda mais o desempenho das páginas.
A medida que essa evolução acontece, conceitos de programação são cada vez mais exigidos, hoje mais do que nunca, javascript é uma linguagem de programação e não mais uma linguagem de script simples usada para fazer validações de formulários.
Se você ainda não tem conceitos de programação de qualquer paradigma e pretende ser um bom profissional em javascript, se quer um conselho de um amigo, eu sugiro que corra atrás o quanto antes, porque isso FAZ muita diferença e você certamente vai achar muito mais divertido programar nessa linguagem.
Galera,
NUNCA, JAMAIS, acredite em alguém que diga que isso não faz diferença. Já ouvi de alguns “Desenvolvedores web” que orientação à objetos em javascript não serve para nada, já que é possível fazer tudo funcionar de forma estrutural. Se algum dia ouvir isso de alguém que você imaginava ser uma pessoa experiente e com certo conhecimento, fica minha dica, ouça-o menos e estude mais.

Mais: Milfont.org/tech – Herança no Javascript

Um grande abraço!