Orientação a objetos em JavaScript, o básico

javascript_oop1

Mais um “capítulo” da série dos pequenos guias sobre orientação a objetos em linguagens de programação e, desta vez, com a inclusão do Javascript¹. Ela é uma linguagem interpretada com orientação a objetos nativa e criada pela Netscape em 1995 para prover a execução de código no lado do cliente² dentro do navegador web homônimo da empresa.

Mais recentemente, com o advento do Node.js, passou a executar código no lado do servidor também! 🙂

E o mínimo necessário em JavaScript para se trabalhar com objetos é o seguinte…

(¹) Ou melhor ECMAScript que é o nome da especificação, enquanto que JavaScript é sua a implementação mais conhecida, uma outra é o JScript usada pelo Internet Explorer.

(²) Eu sei que dentro do navegador só pode ser do lado do cliente mas é bom dar ênfase ao fato, ok?

Criando uma classe

Independente do escopo, dentro de página web ou em uma aplicação em Node.js, a sintaxe é assim:

class «Nome da classe» {
    ...
}

Logo a já “famosa” classe Nome ficaria assim:

class Nome {
}

E agora uma novidade. Uma classe pode também ser definida através de uma expressão de classe que pode ser anônima:

var Nome = class { };

Ou então nomeada:

var Nome = class Nome { };

As expressões de classe foram introduzidas pela especificação ECMA-262 e ainda não são suportadas por todos os navegadores web porém é importante avisar que elas existem.

Outra coisa, o JavaScript não tem mecanismo nativo para inserir código dentro do programa (“include”, “require”, “use” etc), portanto a definição da classe precisará ficar no mesmo arquivo do seu código.

Construtor

Em JavaScript esta classe é chamada de constructor():

class «nome da classe» {
    constructor («parâmetros»){
        ...
    }
}

E no caso da classe Nome ficaria assim:

class Nome {
    constructor (nome,sobrenome){
        this.nome = nome;
        this.sobrenome = sobrenome;
    }
}

Aliás, apesar das funções poderem ser declaradas em uma expressão de função (algo análogo à expressão de classe citada mais acima) isto aqui NÃO é válido:

var constructor = function(nome,sobrenome) { ... };

Ou, ao menos, ainda não o é… 🙂

Criando outros métodos

Os demais (sim, aqueles mesmos) ficariam assim:

class Nome {
    ...
    escreveNome(){
        return this.nome;
    }
    escreveNomeCompleto(){
        return this.nome + " " + this.sobrenome;
    }
    armazenaNome(nome){
        this.nome = nome;
    }
}

Outra coisa, a especificação ECMA-262 também definiu a sintaxe para a criação dos getters e setters dentro de uma classe, então ela poderia ser escrita desta forma:

class Nome {
    ...
    get escreveNome(){
        return this.nome;
    }
    get escreveNomeCompleto(){
        return this.nome + " " + this.sobrenome;
    }
    set armazenaNome(nome){
        this.nome = nome;
    }
}

Há diferença? Ao menos duas!

A primeira é a legibilidade pois olhando a classe já se tem ideia de quais são os métodos que alteram o valor dos atributos — ou propriedades com são chamados na linguagem. A segunda é a sintaxe do código pois você pode tratá-las como se fossem propriedades do objeto e não funções (métodos).

Ou seja, ao invés de usar:

console.log(fulano.escreveNome());
fulano.armazenaNome("José");

Você pode utilizar:

console.log(fulano.escreveNome);
fulano.armazenaNome="José";

O que também ajuda a tornar o código mais legível.

Testando

Mais uma vez um código bem simples:

var giovanni = new Nome("Giovanni","Nunes");
console.log("O primeiro nome é "+giovanni.escreve_nome+".");
console.log("E "+giovanni.escreve_nome_completo+" o nome completo.");

Cujo resultado é

$ node nome.js
O primeiro nome é Giovanni.
E Giovanni Nunes o nome completo.

Sim, o programa é simples e a parte legal é que é possível copiá-lo, colá-lo e testá-lo diretamente dentro do console do navegador web. 🙂

Herança

Para herdar as definições de uma classe — criar uma subclasse — basta indicar na sua definição qual delas você usará como base:

class Supernome extends Nome {
    get escreveNomeCompleto(){
        return this.sobrenome.toUpperCase() + ", "+ this.nome;
    }
}

Agora usando o console do navegador:

> class Nome {
  ...
}
undefined
> class Supernome extends Nome {
    get escreveNomeCompleto(){
        return this.sobrenome.toUpperCase() + ", "+ this.nome;
    }
}
undefined
> var giovanni = new Supernome("Giovanni","Nunes");
undefined
> console.log("E "+giovanni.escreveNomeCompleto+" o nome completo.");
E NUNES, Giovanni o nome completo. 
undefined

Apenas pra variar um pouco.

Console via Node.js

Executando o Node.js diretamente na linha de comando você obtém um console que funciona tal qual o do navegador.

$ node
> var str="Testando 1,2,3"
undefined
> str.length;
14

O “divertido” é que até o padrão de cores é igual.

Finalizando

Assim como acontece em Python e outras linguagens, no JavaScript também não existem mecanismos internos para criação de métodos e atributos de acesso privado. O que é recomendado é o uso do prefixo “_” para identificá-los — também lembrando que esta notação serve para o programador e não para o interpretador.

Para saber um pouco mais consulte o capítulo sobre Classes na referência de JavaScript do Mozilla Developer Network (MDN) e os arquivos usados aqui estão disponíveis no repositório deste blog no GitHub tanto usando as versões pré quanto pós ECMA-262.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s