JavaScript é uma linguagem de programação versátil que permite a criação de programas seguindo diferentes estilos, como o funcional, o orientado a objetos e o imperativo.
Para dar suporte ao paradigma orientado a objetos, o JavaScript incorpora o conceito de classes. Compreender o funcionamento das classes é fundamental, e este artigo serve como um guia sobre o que são classes em JavaScript e como utilizá-las.
O que são Classes em JavaScript?
Na programação orientada a objetos, modelamos sistemas como conjuntos de objetos que interagem entre si. Para que essa interação funcione, os objetos armazenam informações em propriedades e realizam ações definidas como seus métodos. Uma classe define quais propriedades e métodos são compartilhados por objetos do mesmo tipo. Em outras palavras, as classes são como modelos para a criação de objetos.
Terminologia Usada em Classes
Para garantir que estamos todos na mesma página, apresentaremos uma descrição de classes utilizando os termos-chave que empregaremos neste artigo. Se você já está familiarizado com a programação orientada a objetos, pode pular para a próxima seção.
❇️ Uma classe é um projeto para a criação de um objeto. Ela fornece um modelo a partir do qual objetos do mesmo tipo podem ser gerados. A criação de um objeto com base no modelo oferecido pela classe é chamada de instanciação.
❇️ Um membro da classe é tudo aquilo que faz parte da classe. Existem dois tipos principais de membros: métodos e propriedades.
❇️ Uma propriedade é um membro da classe cujo objetivo principal é armazenar valores. Esses valores podem ser simples, como números e textos, ou complexos, como objetos e arrays.
❇️ Algumas propriedades são acessíveis apenas dentro da classe e são denominadas propriedades privadas. Outras podem ser acessadas tanto dentro quanto fora da classe, sendo chamadas de propriedades públicas.
❇️ Um método é uma função definida dentro de uma classe. Portanto, ele pertence à classe e tem acesso tanto às propriedades públicas quanto às privadas. Similarmente às propriedades, também temos métodos públicos e privados.
❇️ Existem alguns métodos que fornecem uma interface para que códigos externos à classe interajam com as propriedades internas. Dois grupos de métodos desempenham essa função: os getters e setters. Os getters são utilizados para obter valores de propriedades da classe, enquanto os setters são empregados para definir valores dessas propriedades.
❇️ Alguns membros são estáticos, o que significa que eles só podem ser acessados diretamente pela classe e não por suas instâncias.
Por outro lado, existem membros da classe que não são estáticos e que só podem ser acessados por meio das instâncias da classe. É necessário instanciar a classe para poder acessar um membro não estático.
Ao instanciar uma classe, um método especial é automaticamente chamado para configurar as propriedades da instância. Esse método é conhecido como função construtora.
Instanciando uma Classe: Uma Explicação Detalhada
Em JavaScript, utilizamos a palavra-chave new
juntamente com o nome da classe para instanciá-la. Por exemplo, vamos instanciar a classe Array
:
const meuArray = new Array()
Criando Classes em JavaScript
Esta seção abordará a criação de uma classe que implemente todos os conceitos apresentados na Seção de Terminologia. Faremos isso por meio de uma série de exemplos, onde cada um se baseia nos anteriores.
Declarando uma Classe Vazia
Para declarar uma classe em JavaScript, usamos a palavra-chave class
, seguida do nome da classe. Em seguida, definimos o corpo da classe, que é delimitado por chaves e contém todos os seus membros.
Aqui está um exemplo de declaração de classe com um corpo vazio:
class Cachorro { }
Agora, podemos instanciar a classe e exibir seu conteúdo:
const animalDeEstimacao = new Cachorro(); console.log(animalDeEstimacao);
Criando Propriedades Públicas
As propriedades públicas são definidas por um identificador e um valor opcional.
class Cachorro { nome = "Rex"; idade; }
Neste caso, a propriedade nome
é inicializada com um valor de string, enquanto a propriedade idade
não tem valor inicial.
const animalDeEstimacao = new Cachorro(); console.log(animalDeEstimacao.nome); console.log(animalDeEstimacao.idade);
Definindo Métodos Públicos
Podemos adicionar métodos à nossa classe dentro de seu corpo. Definimos um método da mesma forma que definiríamos uma função, mas omitimos a palavra-chave function
.
class Cachorro { nome = "Rex"; idade; caminhar() { console.log("Caminhando"); } }
No exemplo acima, definimos o método caminhar
. Cada instância da classe Cachorro
terá este método.
const animalDeEstimacao = new Cachorro(); animalDeEstimacao.caminhar();
Acessando Propriedades de Métodos
Em JavaScript, geralmente acessamos as propriedades de um objeto usando o operador ponto. Por exemplo, se tivéssemos um objeto chamado pessoa
e quiséssemos acessar a propriedade nome
, faríamos o seguinte:
pessoa.nome
No entanto, se desejamos acessar uma propriedade de dentro do próprio objeto, usamos a palavra-chave this
em vez do nome do objeto. Veja este exemplo:
this.nome
A palavra-chave this
se refere ao próprio objeto. Portanto, para acessar as propriedades da classe a partir dos métodos da mesma, usamos a sintaxe this.
.
Criando Propriedades Privadas
Suponha que quiséssemos que as propriedades nome
e idade
definidas anteriormente fossem privadas. Redefiniríamos a classe da seguinte forma:
class Cachorro { #nome = "Rex"; #idade; caminhar() { console.log("Caminhando"); } }
Como podemos observar, as propriedades privadas são especificadas utilizando o caractere #
(cerquilha). Se tentarmos acessá-las diretamente, receberemos um erro.
const cachorro = new Cachorro(); cachorro.#nome
Criando Métodos Getter e Setter
Agora, as propriedades nome
e idade
da classe são privadas. Portanto, elas só podem ser acessadas por métodos dentro da própria classe.
Se quisermos permitir que códigos externos à classe acessem essas propriedades, definimos métodos getters e setters. Vamos implementar isso para a propriedade nome
.
class Cachorro { #nome = "Rex"; #idade; get nome() { return this.#nome; } set nome(valor) { this.#nome = valor; } caminhar() { console.log("Caminhando"); } }
Com a classe definida acima, podemos alterar o valor da propriedade nome
e exibi-la da seguinte forma:
const animalDeEstimacao = new Cachorro(); // Definindo o nome animalDeEstimacao.nome = "Max"; // Obtendo o nome console.log(animalDeEstimacao.nome);
Criando Métodos Privados
Assim como as propriedades privadas, os métodos privados são prefixados com o caractere #
. Portanto, a declaração de um método privado seria semelhante a esta:
class Cachorro { #nome = "Rex"; #idade; get nome() { return this.#nome; } set nome(valor) { this.#nome = valor; } #aumentarIdade() { this.#idade++; } #diminuirIdade() { this.#idade--; } caminhar() { console.log("Caminhando"); } }
Se tentarmos acessar esses métodos de fora da classe, receberemos um erro.
const animalDeEstimacao = new Cachorro(); animalDeEstimacao.#aumentarIdade();
Criando um Método Construtor
Podemos também definir o método construtor. Este método é automaticamente chamado sempre que uma nova instância da classe é criada. O método construtor é usado para inicializar as propriedades. Neste exemplo, inicializaremos a idade e o nome com os argumentos fornecidos pelo usuário durante a instanciação.
class Cachorro { #nome; #idade; constructor(nome = "Cachorro", idade = 0) { this.#nome = nome; this.#idade = idade; } get nome() { return this.#nome; } set nome(valor) { this.#nome = valor; } #aumentarIdade() { this.#idade++; } #diminuirIdade() { this.#idade--; } caminhar() { console.log("Caminhando"); } }
Ao instanciarmos a classe, podemos fornecer o nome e a idade:
const animalDeEstimacao = new Cachorro('Rex', 3); console.log(animalDeEstimacao.nome);
Criando Propriedades e Métodos Estáticos
Conforme mencionado, os membros estáticos podem ser acessados sem a necessidade de instanciar a classe. No exemplo abaixo, criaremos uma propriedade e um método estáticos.
class Cachorro { #nome; #idade; static genero = "Canis"; constructor(nome = "Cachorro", idade = 0) { this.#nome = nome; this.#idade = idade; } static latir() { console.log("Au au"); } get nome() { return this.#nome; } set nome(valor) { this.#nome = valor; } #aumentarIdade() { this.#idade++; } #diminuirIdade() { this.#idade--; } caminhar() { console.log("Caminhando"); } }
Agora, podemos acessar a propriedade e o método estáticos diretamente, sem criar uma instância da classe.
console.log(Cachorro.genero); Cachorro.latir();
Herança
As classes podem herdar propriedades de outras classes. A classe que herda membros de outra classe é chamada de superclasse, enquanto a classe da qual se herda os membros é a classe base ou subclasse.
Para criar uma superclasse em JavaScript, usamos a palavra-chave extends
. Aqui está um exemplo onde herdamos da classe Cachorro
.
class Rottweiler extends Cachorro { constructor(nome, idade) { super(nome, idade); this.raca = 'rottweiler'; } }
Como podemos ver, a classe é basicamente a mesma de antes, porém dentro do construtor, chamamos a função super
. A palavra-chave super
se refere ao construtor da classe base. Portanto, chamamos o construtor da classe base dentro da nossa superclasse, passando o nome e a idade.
const meuAnimalDeEstimacao = new Rottweiler(); console.log(meuAnimalDeEstimacao);
Conclusão
Neste artigo, exploramos o conceito de classes. Vimos o que são, os membros que podem possuir e as diferentes classificações para esses membros. Em seguida, ilustramos tudo isso com exemplos práticos.
Em seguida, você pode querer explorar perguntas comuns em entrevistas sobre programação orientada a objetos.