Introdução de Orientação a Objetos em JavaScript(JOOP)(Parte 2)

No capítulo anterior sobre Orientação a Objetos você aprendeu a utilizar uma função, que também é um objeto, na criação de um construtor. Também foi visto o conceito de construtor, métodos e propriedades apesar de não constar na especificação do Ecma o conceito de métodos.
Abordaremos hoje o início do conceito de “Herança Prototípica” no JavaScript.
Respeitando os padrões aprendidos no capítulo anterior sobre JOOP aqui do TutsMais, vamos criar um construtor ou uma função construtora vazia:

function TutsMais() {}

Agora vamos utilizar esse construtor, extender e acrescentar um valor ou propriedade ao nosso construtor:

TutsMais.prototype.carro = function() {
	alert( "Teste" );
}

// Aproveitando pra relembrar o nosso Creational Pattern
var Objeto = new TutsMais();

Agora vamos ver o resultado disso no console.log() (ctrl + shift + j , chrome) :

objetos

Humm que tal? Você já conseguiu entender?
Antes de dar continuidade vou explicar mais um conceito de Orientação a Objetos. O “Instanciar”, como você mesmo pode observar, corresponde a criação física e concreta do Modelo ou da Função Construtora TutsMais.
Agora que você conhece cada membro de uma herança, e já consegue fazer uma herança de uma função construtora, vamos tentar criar uma herança usando uma palavra reservada no JavaScript, o “this”:

function TutsMais() {
    this.PropriedadeA = "Verde";
}

TutsMais.prototype.cores = function() {
    return this;
}

var Objeto = new TutsMais();

console.log( Objeto.cores() );

Resultado:

propriedades

Você já deve estar imaginando o que aconteceu não é? Na função construtora “TutsMais” nós agregamos ou fizemos uma herança usando a propriedade com o prototype “cores” e adicionamos ao Objeto “this” a PropriedadeA: “Verde” . Retornamos o “this” na “herança prototypica” logo abaixo, que agora passou a possuir a PropriedadeA: “Verde”.
“This” é a representação física do Objeto que criamos dentro da construtora e da “herança prototípica” que criamos.
Agora vamos usar uma variação, mas que faz e tem o mesmo resultado da herança anterior:

function TutsMais( PropriedadeA ) {
    this.PropriedadeA = PropriedadeA;
}

TutsMais.prototype.cores = function() {
    return this;
}

var Objeto = new TutsMais( "Verde" );

console.log( Objeto.cores() );

A única diferença dessa herança, pra anterior, é que passamos o valor do Objeto “Propriedade A” ou setamos o valor do “This” ( Objeto ), já como parâmetro da função, na hora que instanciamos o Objeto com o “This”.

Simplificando:

function Modelo( objeto ) {
    this.objeto = objeto; // Objeto this é igual ao "valordoobjeto"
}

Modelo.prototype.propriedade = function() {
    return this; // This possui e herda o "valordoobjeto" da construtora
}

var Objeto = new Modelo( "valordoobjeto" ); // Passamos o valor do Objeto

console.log( Objeto.propriedade() ); // Chamamos a herança prototípica que retorna o "this"

Com isso, praticamente aprendemos a criar uma herança clássica e prototípica em JavaScript.

Vamos brincar mais um pouco?

Exemplo 1:

/*
 * Emulando a Classe Cachorro no JavaScript
 */
function Cachorro( osso, latido ) {
    this.osso = osso;
    this.latido = latido;
}

Cachorro.prototype.morder = function() {
    return ( "Morde o osso: " + this.osso );
}

Cachorro.prototype.latir = function() {
    return ( "Late assim: " + this.latido );
}

// Vamos chamar o nosso Cachorro de Rex
var Rex = new Cachorro( "osso grande!", "au au" );

// Nosso Rex vai Latir e Morder agora, são as duas ações ;D
console.log( Rex.latir() + " " + Rex.morder() );

Exemplo 2:

// Variação da Classe Cachorro

var Cachorro = function( osso, latido ) {
    this.osso = osso;
    this.latido = latido;
}

Cachorro.prototype.morder = (function() {
    return ( "Morde o osso: " + this.osso );
})

Cachorro.prototype.latir = function() {
    return "Late assim: " + this.latido;
}

var Rex = new Cachorro( "Osso!", "au au" );

console.log( Rex.morder() + " " + Rex.latir() );

Exemplo 3:

/*
 * Emulando a Classe Carro no JavaScript
 * Aqui Homenageio um dos meus mestres
 */
function Carro( modelo ) {
    this.modelo = modelo;
    this.cor = "prata";
    this.ano = "2012";

    // Aqui crio um gerador de informações.. ;D
    this.getInformacao = function() {
        return this.modelo + " " + this.ano;
    };
}

Carro.prototype.andar = function() {
    return "Eu ando de: " + this.modelo + ", sempre que eu tô com preguiça de andar a pé..";
}

Carro.prototype.pintar = function() {
    return "Eu tenho um carro na cor: " + this.cor;
}

var meuCarro = new Carro( "Fusca" );

// Gerar informações do Fusca:
console.log( meuCarro.getInformacao() ); // Fusca 2012 ;D

/*
 * Essa informação está errada, meu fusca é de 1990, eu posso
 * alterar essa informação aqui fora..
 * Observe.. ;D
 */
meuCarro.ano = "1990";

// Vamos gerar novamente essas informações sobre o meu fusca
console.log( meuCarro.getInformacao() ); // Fusca 1990 ;D

// Chamando os protótipos..

console.log( meuCarro.andar() ); // Eu ando de: Fusca, sempre que eu tô com preguiça de andar a pé..
console.log( meuCarro.pintar() ); // Eu tenho um carro na cor: prata

// Se eu quiser criar outro carro? Posso?

var meuCarro = new Carro( "Ferrari" );

// Essa é a famosa herança em JavaScript. Com reutilização de código.
console.log( meuCarro.getInformacao() );

Exemplo 4:

/*
 * Vamos Emular Mulheres?
 * Como representaríamos mulheres em JS?
 */
var Mulheres = (function( idade, cor, altura, cabelo ) {
    this.idade = idade;
    this.cor = cor;
    this.altura = altura;
    this.cabelo = cabelo;

    this.setInfo = (function( idade, cor, altura, cabelo ) {
        this.idade = idade;
        this.cor = cor;
        this.altura = altura;
        this.cabelo = cabelo;
    })
});

    this.getInfo = (function() {
        return ( this.idade + " " + this.cor + " " + this.altura + " " + this.cabelo );
    });
});

Mulheres.prototype.descrever = (function() {
    return ( "A mulher tem a idade: " + this.idade + " a cor: " + this.cor +
             " altura: " + this.altura + " com os cabelos: " + this.cabelo );
});

var Suzana = new Mulheres();

Suzana.setInfo( "21", "branca", "1.74", "loira" );
console.log( Suzana.getInfo() );

var Carol = new Mulheres( "22", "Morena", "1,65", "Cabelos Escuros" );
console.log( Carol.descrever() );

Exemplo 5:

// Criamos a Classe
var Classe = (function() {

})

Classe.prototype.nascer = (function() {

})

Classe.prototype.morrer = (function() {

})

Classe.prototype.respirar = (function() {

})

var Mulheres = (function( nome ) {
    this.nome = nome
});

Mulheres.prototype = new Classe(); // definimos que Mulher vai usar a Classe ou Modelo emulada como um protótipo
Mulheres.prototype.constructor = Mulheres(); // Alterando o construtor do objeto usado como protótipo
Mulheres.prototype.programar = (function() { // método programar apenas para Mulheres
    return ( "A : " + this.nome + " é doida." );
});

var Programadora = new Mulheres( "Tânia" ); // Setando o valor de nome
console.log( Programadora.programar() ) // usando o método definido em Mulheres
console.log( Programadora.nome );

Exemplo 6:

var MaquinadoTempo = (function() {
var destino = "5 de Outubro, 1955";
    this.getDestino = (function() {
        return ( destino );
    });
});

var delorean = new MaquinadoTempo();
console.log( delorean.getDestino() );

Exemplo 7:

// Isolando o construtor
function Carro() {
    this.roncar = function() {
        console.log( "vrumm vrumm" );
    }
}

var meuCarro1 = new Carro();
var meuCarro2 = new Carro();

console.log( meuCarro1.constructor );
console.log( meuCarro2.constructor );

Exemplo 8:

function Carro() {}

Carro.prototype.roncar = function() {
    console.log( "Vruumm Vrumm");
}

var meuCarro1 = new Carro();
var meuCarro2 = new Carro();

meuCarro1.roncar();
meuCarro2.roncar();

Exemplo 9:

// Usando a criação de Objetos literais
var veiculo = veiculo || {};

veiculo.dirigir = (function () {
    console.log( "vrooom..." );
});

// Usando o Object.create
var carro = Object.create( veiculo );

carro.roncar = (function() {
    console.log( "vroom vroom" );
});

var meuCarro = Object.create( carro );

meuCarro.roncar();
meuCarro.dirigir();

Exemplo 10:

/* 
 * Isso poderia ser uma Implementação do Decorator.
 * Sim, é um outro Pattern.
 * Em breve vamos entrar mais em detalhes..
 * Criamos o Construtor Veiculo:
 */
var Veiculo = (function( tipoVeiculo ){
    this.tipoVeiculo = tipoVeiculo || "carro";
    this.modelo = "comum";
    this.licenca = "00000-000";
})

var testeInstancia = new Veiculo( "carro" );
console.log( testeInstancia );

// Saída:
// Veiculo: carro, modelo: comum, licença: 00000-000

// Vamos criar uma nova instancia do Veículo, para ser decorada...
var caminhao = new Veiculo( "caminhao" );

// Adicionando novas funcionalidades ao Veículo
caminhao.setModelo = (function( modeloNome ){
    this.modelo = modeloNome;
});

caminhao.setCor = (function( cor ){
    this.cor = cor;
});
    
// Testando o valor dos setters e observando se o valor está correto
caminhao.setModelo( "Ferrari" );
caminhao.setCor( "Vermelho" );

console.log( caminhao );

// Saída:
// Veiculo: caminhao, modelo: Ferrari, cor: Vermelho

// Demonstrando que o "Veiculo" ainda está inalterado

var segundaInstancia = new Veiculo( "carro" );
console.log( segundaInstancia );

Exemplo 11:

/*
 * Fazendo outra Implementação do Decorator
 * Baseado na implementação de um dos nossos mestres
 * Só utilizando o que aprendemos aqui no TutsMais
 */
var Carro = (function() { 
    this.custo = (function() { return 6000; }); 
    this.custoamais = (function() { return 1000; }); 
}); 

// Decorator 1 - Adicionamos uma Peça ao valor do Carro.
var Som = (function( carro ) { 
    // Decoramos o custo do Carro que vem do Construtor de cima.
    var c = carro.custo(); 
    carro.custo = (function() { 
        // Retornamos a o Custo e adicionamos o valor do Som.
        return c + 100; 
    }) 
});

// Decorator 2 - Variamos o tipo da função, mas o ideal é que
// seja sempre: Todas as Funções do tipo: Anônimas ou Todas do tipo definido.
function LuzDianteira( carro ){
    var c = carro.custo(); 
    carro.custo = (function(){
        return c + 200;
    });
}
 
// Decorator 3
function Farol( carro ){
    var c = carro.custo(); 
    carro.custo = (function(){
        return c + 250;
    });
}

// Substituição do carro nos parâmetros, por preco.
var preco = new Carro(); 

Som( preco ); 
LuzDianteira( preco );
Farol( preco );

console.log( preco.custo() ); // Retorna 6550

console.log( preco.custoamais() ); // Retorna 1000

var total = preco.custo() + preco.custoamais();

console.log( total ); // Retorna 7550

Exemplo 12: (Bônus usando Canvas)

// Primeiro crie a tag do canvas como no exemplo: 
// <canvas id="canvas" width="150" height="150">Seu browser não suporta Canvas...</canvas>​


/*
 * JavaScript Html5 Canvas
 * Copyright (C) 2012 - Rodrigo Nery
 *
 * Esse triângulo é free; Você pode redistribuir ou modificar
 * Sobre os termos da GNU General Public License
 * 
 * License is available at http://www.gnu.org/licenses/gpl.html
 */

// Meu NameSpace, evitando qualquer conflito e deixando mais bonito!
var NS = NS || {};

// Criando minha Classe com o NameSpace
NS.Class = (function() {

    // Meu Construtor pegando o id Canvas e o Contexto 
    var Canvas = (function() {
        this.canvas = document.getElementById("canvas");
        this.ctx = canvas.getContext("2d");
    });

    // Crio meu Triangulo e herdo o construtor
    Canvas.prototype.triangulo = (function() {

        // Desnecessário porém é boa prática verificar o contexto 
        if( this.ctx ) {
            // Cor do Triângulo em HSL ou Hue Saturation and Lightness
            this.ctx.fillStyle = "hsl( 353, 100%, 72% )";
            // Começo o Path
            this.ctx.beginPath();
            // O ponto de partida do desenho são as coordenadas 35,50
            this.ctx.moveTo( 35,50 ); 
            this.ctx.lineTo( 150,100 );
            this.ctx.lineTo( 150,15 );
            this.ctx.fill();
        }
    });
    // Retorno o Objeto pra ser usado fora da Classe
    return new Canvas();

// Auto Executo a Classe on Dom Load..
}( NS.Class ));

// Invoco o Objeto Triângulo com HTML5 ;D
NS.Class.triangulo();

Exemplo 13: (Bônus usando Canvas MicroTemplate)

/*
 * JavaScript Html5 Canvas
 * Copyright (C) 2012 - Rodrigo Nery
 *
 * Esse MicroTemplate é free; Você pode redistribuir ou modificar
 * Sobre os termos da GNU General Public License
 * 
 * License is available at http://www.gnu.org/licenses/gpl.html
 */

// Criando o NameSpace que verifica se já existe e se não existir, cria.
var Tag = Tag || {};

Tag.Class = (function() { 
  
var Template = (function() {
    this.elemento = document.createElement( 'canvas' );
    this.ID = document.getElementById( 'canvas' );
})

// Criando a Tag Canvas...
Template.prototype.criarTag = (function() {
    this.elemento.id = 'canvas';
    this.elemento.className = 'canvas';
    this.elemento.setAttribute( 'width', '540px' );
    this.elemento.setAttribute( 'height', '540px' );
    this.elemento.innerHTML = 'Seu Browser não suporta a tag Canvas.';
    this.ID.appendChild( this.elemento );
})

    return new Template();
}( Tag.Class ));

// Iniciando a Tag
Tag.Class.criarTag();

Considerações Finais

Bom, por hoje é só… Tente absorver o máximo dos conceitos que foram vistos!
Espero que todas às suas dúvidas sobre essa parte de Orientação a Objetos e herança sejam solucionadas depois desse post.
Na próxima semana, vou falar sobre Objetos literais, entre outros…
Espero você lá!

Esta entrada foi publicada em javaScript. Adicione o link permanenteaos seus favoritos.

2 respostas a Introdução de Orientação a Objetos em JavaScript(JOOP)(Parte 2)

  1. Rodrigo disse:

    Acho q o site esta com algum problema de codifica

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">