Aprenda Javascript

  • Página Inicial
  • Contato!
  • Tudo sobre Javascript Parte 1!
  • Tudo sobre Javascript Parte 2!
  • Tudo sobre Javascript Parte 3!
  • Tudo sobre Javascript Parte 4!
  • Tudo sobre Javascript Parte 5!
  • Tudo sobre Javascript Parte 6!
  • Tudo sobre Javascript Parte 7!
  • Tudo sobre Javascript Parte 8!
  • Orientação a Objetos em Javascript

    Criando Classes e Objetos

    Basicamente, criamos uma classe em Javascript assim:

    
    const Pessoa = function() {
        // Se houvesse herança de uma classe com o nome Humano, ela seria assim, também serve pra chamar métodos da classe pai:
        // Humano.call(this);
    
        this.nome = "";
        this.telefone = "";
        this.cpf = "";
    
        this.mostrar = function() {
            alert("Nome: " + this.nome + "\nTelefone: " + this.telefone + "\nCPF: " + this.cpf);
        };
    };
    
    

    No caso acima, todo método ou atributo com this (que é substituído pelo objeto) é público, para simular privados seria algo como var nome = "".

    Note que não existia a palavra class para criar classes, por isso é usado uma função anônima para isso. As funções também são utilizadas com uma função anônima.

    Dessa forma basta criar os objetos assim:

    
    var c = new Pessoa(); // Criação do objeto
    
    // Atributos do objeto:
    c.nome = "Carlos";
    c.telefone = "1234-5678";
    c.cpf = "123.456.789-01";
    
    // Invocação do método:
    c.mostrar();
    
    

    Também podemos criar objetos atribuindo diretamente à variável ou constante, dessa forma:

    
    var c = {
        nome: "Carlos",
        telefone: "1234-5678",
        cpf: "123.456.789-01",
        mostrar: function() {
            alert("Nome: " + this.nome + "\nTelefone: " + this.telefone + "\nCPF: " + this.cpf);
        }
    };
    
    c.mostrar();
    
    

    Ou criando uma nova instância de Object (objeto padrão do Javascript) e adicionando os atributos e métodos, assim:

    
    var c = new Object();
    
    c.nome = "Carlos";
    c.telefone = "1234-5678";
    c.cpf = "123.456.789-01";
    
    c.mostrar = function() {
        alert("Nome: " + this.nome + "\nTelefone: " + this.telefone + "\nCPF: " + this.cpf);
    };
    
    c.mostrar();
    
    

    No entanto, atualmente podemos criar classes em Javascript, o código reescrito ficaria assim:

    
    class Pessoa {
        constructor() {
            this.nome = "";
            this.telefone = "";
            this.cpf = "";
        }
    
        mostrar() {
            alert("Nome: " + this.nome + "\nTelefone: " + this.telefone + "\nCPF: " + this.cpf);
        }
    };
    
    var c = new Pessoa();
    
    c.nome = "Carlos";
    c.telefone = "1234-5678";
    c.cpf = "123.456.789-01";
    
    c.mostrar();
    
    

    Note que agora tivemos que criar um construtor com os atributos, e os métodos não utilizam "function" no começo.

    PS: Para pegar o nome da classe, use this.constructor.name.

    Quando criamos uma classe, temos mais trabalho para fazê-la, mas depois que ela está pronta, podemos criar quantos objetos precisarmos vindos dessa mesma classe, e o programa principal fica mais simples, menor e mais natural. Os objetos criados dessa mesma classe são independentes entre si e o status de um não interfere no outro. Essa é uma das vantagens da orientação a objetos.

    Construtores

    Podemos também criar construtores nas classes, dessa forma:

    
    class Pessoa {
        constructor(nome, telefone, cpf) {
            this.nome = nome;
            this.telefone = telefone;
            this.cpf = cpf;
        }
    
        mostrar() {
            alert("Nome: " + this.nome + "\nTelefone: " + this.telefone + "\nCPF: " + this.cpf);
        }
    };
    
    

    O this é o atributo da classe, e o que está a direita, o parâmetro do construtor.

    Aí, desse modo, temos que passar os parâmetros na criação do objeto:

    
    var c = new Pessoa("Carlos", "1234-5678", "123.456.789-01");
    
    c.mostrar();
    
    

    PS: Podemos também destruir os objetos usando delete, assim:

    
    var c = new Pessoa("Carlos", "1234-5678", "123.456.789-01");
    
    c.mostrar();
    
    delete c;
    
    

    PS: Caso num construtor precise inicializa um atributo como nulo, use null.

    Métodos Estáticos

    Também podemos usar métodos estáticos de classes em Javascript, sendo que nesse caso é atributo da classe, por exemplo:

    
    class Veiculo {
        static verifCombustivel() {
            alert("O combustível do veículo é gasolina!");
        }
    };
    
    

    E para chamar, podemos chamar diretamente pela classe, sem criar um objeto, por exemplo:

    
    Veiculo.verifCombustivel();
    
    

    No entanto, não é possível criar atributos estáticos diretamente, apenas simulá-los, por exemplo:

    
    class Veiculo {
        static verifCombustivel() {
            alert("O combustível do veículo é " + Veiculo.combustivel + "!");
        }
    };
    
    Veiculo.combustivel = "gasolina";
    
    Veiculo.verifCombustivel();
    
    

    PS: Métodos estáticos só podem trabalhar outros métodos e atributos quando estes também forem estáticos, e não podem ser sobrepostos. E atributos estáticos é recomendável eles serem inicializados, e nunca se deve utilizar o this neles.

    Encapsulamento

    Colocando this nos atributos ou métodos, mostra que ela é pública, para tornar ela privada, coloque um _ antes do nome do atributo, assim:

    
    class Media {
        constructor() {
            // Atributos públicos:
            this.nota1 = 0;
            this.nota2 = 0;
    
            // Atributo supostamente privado:
            this._med = (this.nota1 + this.nota2) / 2;
        }
    };
    
    

    Na prática, não existe o encapsulamento real em Javascript, apenas uma forma de sinalizar quais atributos não devem ser acessados. Na forma antiga, usando functions no lugar das classes, definíamos o que era público com this e o que era privado sem ele e com o var na frente.

    PS: Recentemente podemos usar # ao invés do underline na frente do atributo pra indicar que ele é "privado", mas isso não funciona em todos os navegadores.

    Mas podemos criar métodos públicos para acessar essas variáveis "privadas", mesmo se todas as variáveis forem "privadas". Veja o código acima alterado:

    
    class Media {
        constructor(n1, n2) {
            // Atributos supostamente privados:
            this._nota1 = n1;
            this._nota2 = n2;
    
            this._med = (this._nota1 + this._nota2) / 2;
        }
    
        // Método público que retorna a conta:
        
        get med() {
            return this._med;
        }
    
        // Método público que muda a média diretamente:
        
        set med(value) {
            this._med = value;
        }
    };
    
    

    Podemos ver que os métodos getters e setters tem a indicação get e set antes da função.

    E na instância:

    
    var a = new Media(10, 5);
    
    alert("A média é " + a.med);
    
    

    PS: O uso e a a atribuição de métodos getters e setters são iguais às variáveis, pois são considerados propriedades, e não métodos, portanto, usar o setter do método criado ficaria assim:

    
    var a = new Media(10, 5);
    
    a.med = 10;
    
    alert("A média é " + a.med);
    
    

    Herança

    Primeiramente, crie uma classe genérica assim:

    
    class Animal {
        vivo() {
            alert("O Animal está Vivo!");
        }
    };
    
    

    Para fazer a herança numa nova classe, usamos o extends, dessa forma:

    
    class Gato extends Animal {
    
    };
    
    

    PS: Isso é uma herança pobre, a classe herdeira pode ter novos atributos e métodos.

    Dessa forma, podemos chamar o método assim:

    
    var g = new Gato();
    
    g.vivo();
    
    

    PS: Javascript não permite herança múltipla. E caso use construtores, sempre chame a classe mãe com o método super dentro do construtor da classe filha, mesmo se não houver parâmetros.

    Polimorfismo

    Pegando o mesmo exemplo da classe anterior, podemos sobrepor o método da classe pai na classe filha, assim:

    
    class Gato extends Animal {
        vivo() {
            alert("O Gato está Vivo!");
            super.vivo(); // Chamada do método da classe pai
        }
    };
    
    

    E exibir assim:

    
    var g = new Gato();
    
    g.vivo();
    
    

    No Javascript podemos usar o polimorfismo de sobreposição, mas não o de sobrecarga.

    PS: Pode ser necessário chamar o construtor da classe pai com super, caso a classe herdeira tenha parâmetros, mesmo se a classe pai não tiver nenhum.

    Métodos Abstratos

    Na teoria, não existem métodos abstratos em Javascript, mas podemos simulá-los, criando uma exceção de erro nos métodos que queremos implementar, veja a alteração da classe anterior:

    
    class Animal {
        // Simulação de método abstrato:
        vivo() {
            throw new Error("Implementação do método 'vivo' requerida");
        }
    };
    
    

    E nas classes filhas que terão que implementar o método, basta fazer a implementação como achar necessário:

    
    class Gato extends Animal {
        // Implementação do método:
        vivo() {
            alert("O Gato está Vivo!");
        }
    };
    
    

    Exercícios de POO

    Crie uma classe com o nome Eletrodomestico que servirá de base para outras classes:

    
    class Eletrodomestico {
        constructor(marca, ligado) {
            this._marca = marca;
            this._ligado = ligado;
        }
    
        usando() {
            document.write("Estou utilizando o Eletrodoméstico!");
        }
    
        get marca() {
            return this._marca;
        }
    
        set marca(value) {
            this._marca = value;
        }
    
        get ligado() {
            return this._ligado;
        }
    
        set ligado(value) {
            this._ligado = value;
        }
    };
    
    

    Baseado nessa classe, crie várias classes com eletrodomésticos diversos, fazendo a sobreposição do método funcionando, mas chamando também a função da classe pai, por exemplo:

    
    class Geladeira extends Eletrodomestico {
        constructor(marca, ligado) {
            // Chamada do construtor da classe pai:
            super(marca, ligado);
        }
    
        usando() {
            super.usando();
            document.write(" E é uma geladeira!");
        }
    };
    
    

    E na instância:

    
    var gelad = new Geladeira("Brastemp", true);
    
    gelad.usando();
    document.write("<br/>O Eletrodoméstico está ligado? " + gelad.ligado);
    
    

    Tente também colocar o método da classe Eletrodomestico como abstrato e implementar eles nas classes filhas.

    Prototype

    Em Javascript, podemos também criar atributos e métodos em classes por protótipos, como por exemplo:

    
    class Comida {
    
    };
    
    Comida.prototype.sabor = "salgado";
    
    Comida.prototype.verifSabor = function() {
        document.write("O sabor da comida é " + this.sabor + ".<br/>");
    };
    
    

    Lembrando que todos os objetos criados terão os mesmos valores definidos nos protótipos, por exemplo:

    
    var arroz = new Comida();
    var feijao = new Comida();
    
    arroz.verifSabor();
    feijao.verifSabor();
    
    

    PS: Não dá pra usar métodos estáticos como protótipos.