Skip to main content

📘 Orientação a Objetos -- Herança, Sobrescrita e Operadores de Comparação

Observe o seguinte código de exemplo relativo à declaração da classe PJ (que é uma subclasse da classe Pessoa). Este exemplo aprofunda os conceitos de herança, sobrescrita de métodos, encapsulamento com validação, e o uso de operadores de comparação em JavaScript.


💻 Código Completo

Arquivo: PJ.js

// Arquivo criado em projeto no www.stackblitz.com denominado PJ.js (Pessoa Jurídica)
// Arquivo criado dentro de uma pasta /objetos/pessoas na raiz do projeto
// Objetivo do exemplo: demonstrar conceitos de Herança e sobrescrita de métodos,
// bem como encapsulamento adicionados de condicionais e operadores de comparação

const Pessoa = require('./Pessoa');

class PJ extends Pessoa {

#cnpj;

setCNPJ(cnpj) {

/*
Operadores de comparação:
< : menor que
> : maior que
<= : menor ou igual que
>= : maior ou igual que
*/

if (cnpj) {

if (cnpj.length < 18) {
return false;
}

this.#cnpj = cnpj;
return true;

} else {

return false;

}

}

getCNPJ() {
return this.#cnpj;
}

// Sobrescrita do método setEmail()
setEmail(email) {

/*
Operadores de comparação:
== : igualdade frouxa
=== : igualdade estrita
!= : diferença frouxa
!== : diferença estrita
*/

if (email !== '') {

if (email.includes('@')) {

super.setEmail(email);

return true;

}

} else {

return false;

}

}

}

module.exports = PJ;

📘 Comentários e Explicações Linha a Linha

Linhas 01--04

// Arquivo criado em projeto no www.stackblitz.com denominado PJ.js (Pessoa Jurídica)
// Arquivo criado dentro de uma pasta /objetos/pessoas na raiz do projeto
// Objetivo do exemplo: demonstrar conceitos de Herança e sobrescrita de métodos,
// bem como encapsulamento adicionados de condicionais e operadores de comparação

Esses comentários descrevem informações importantes sobre o arquivo.

São apresentados:

  • o nome do arquivo;
  • sua localização dentro do projeto;
  • o objetivo pedagógico do exemplo.

Neste caso, o objetivo é demonstrar quatro conceitos fundamentais da Programação Orientada a Objetos:

  • herança;
  • sobrescrita de métodos;
  • encapsulamento;
  • operadores de comparação.

Linha 06

const Pessoa = require('./Pessoa');

Importa a classe Pessoa, localizada no arquivo Pessoa.js.

Essa importação permite reutilizar toda a implementação já existente na classe base.

Sem essa linha não seria possível utilizar:

extends Pessoa

Linhas 08--10

class PJ extends Pessoa {

#cnpj;

Nesta parte ocorre a declaração da classe PJ (Pessoa Jurídica).

Observe o uso da palavra-chave:

extends

Ela informa ao JavaScript que a classe PJ será uma especialização da classe Pessoa.

Isso significa que a classe PJ herdará automaticamente métodos como:

  • setNome();
  • getNome();
  • setEmail();
  • getEmail().

Além desses métodos herdados, a classe declara um atributo privado:

#cnpj

Esse atributo somente poderá ser acessado pelos métodos internos da própria classe.


Linhas 12--37

setCNPJ(cnpj) {

...

}

Este método é responsável por atribuir um valor ao atributo privado #cnpj.

O processo ocorre em três etapas.

Primeira etapa

Verifica se algum valor foi informado.

if (cnpj)

Caso o parâmetro seja vazio (null, undefined ou string vazia), o método retorna:

false

Segunda etapa

Caso exista um valor, verifica-se seu comprimento.

if (cnpj.length < 18)

O operador utilizado é:

<

(menor que)

O objetivo é impedir que CNPJs incompletos sejam armazenados.

O formato esperado é semelhante a:

12.345.678/0001-90

que possui 18 caracteres.

Terceira etapa

Se todas as validações forem satisfeitas:

this.#cnpj = cnpj;

o valor é armazenado no atributo encapsulado.

Em seguida o método retorna:

true

indicando sucesso na operação.


Linhas 39--41

getCNPJ() {
return this.#cnpj;
}

Método responsável por retornar o valor armazenado no atributo privado #cnpj.

Como o atributo é encapsulado, somente esse método pode disponibilizar seu conteúdo para código externo.

Esse padrão é conhecido como Getter.


Linha 43

// Sobrescrita do método setEmail()

Este comentário informa que o próximo método substituirá o comportamento original herdado da classe Pessoa.

Em Programação Orientada a Objetos isso recebe o nome de sobrescrita de método.


Linhas 44--70

setEmail(email) {

...

}

Embora a classe Pessoa já possua um método chamado setEmail(), a classe PJ decide implementar uma versão mais especializada.

Essa nova implementação adiciona novas regras de validação.

Primeira validação

if (email !== '')

Utiliza o operador:

!==

(diferente estrito)

Ele verifica se o e-mail não é uma string vazia.

Diferentemente do operador !=, o operador !== também compara o tipo do dado.

Segunda validação

email.includes('@')

O método includes() verifica se existe o caractere:

@

na string.

Caso não exista, entende-se que o e-mail é inválido.

Chamada ao método da classe base

super.setEmail(email);

A palavra-chave:

super

permite acessar a implementação original da classe mãe.

Ou seja, além das novas validações implementadas em PJ, continua sendo executada a lógica já existente na classe Pessoa.

Essa técnica evita duplicação de código e promove reutilização.


Linhas 72--74

}

module.exports = PJ;

A linha 72 encerra a definição da classe.

Na sequência:

module.exports = PJ;

exporta a classe para que ela possa ser utilizada em outros arquivos do projeto através do comando:

require('./PJ');

📌 Conceitos-Chave Envolvidos


Conceito Explicação


extends Permite que uma classe herde atributos e métodos de outra classe.

Herança Mecanismo de reutilização de código entre classes.

Sobrescrita de método Permite redefinir um método herdado adicionando novas regras.

super Executa o método da classe base durante a sobrescrita.

Encapsulamento Protege atributos privados utilizando métodos públicos.

#atributo Campo privado disponível no JavaScript moderno.

length Retorna a quantidade de caracteres de uma string.

includes() Verifica se determinado texto existe dentro de uma string.

Operadores < e !== Utilizados para validações e controle do fluxo do programa.

module.exports Exporta a classe para reutilização em outros módulos.


💡 Dicas do Professor

  • Utilize herança quando uma classe representar uma especialização de outra.
  • Use sobrescrita quando precisar reaproveitar um método herdado, mas com regras específicas.
  • Utilize super.metodo() quando quiser executar o comportamento original da classe base.
  • Validações com operadores de comparação ajudam a proteger os dados encapsulados.

Utilização das Classes -- Arquivo usaPessoas.js

Abaixo é apresentado um complemento que deve ser colocado ao final do arquivo usaPessoas.js, responsável pela instanciação dos objetos Pessoa, PF e PJ para demonstração do uso dos objetos.


💻 Código Completo

Arquivo: usaPessoas.js

// Arquivo criado em projeto no www.stackblitz.com denominado usaPessoas.js
// Arquivo criado dentro de uma pasta /objetos na raiz do projeto
// Objetivo do exemplo: demonstrar a utilização dos conceitos de encapsulamento
// com adição de condicionais e Herança
// Classes Pessoa, PF e PJ disponíveis na pasta /objetos/pessoas

console.log("==== Objeto Pessoa =====");

const Pessoa = require('./pessoas/Pessoa');

const x = new Pessoa();

// resposta = x.setNome('Leandro');
resposta = x.setNome('');

console.log(resposta);

if (resposta) {
console.log(x.getNome());
} else {
console.log("Nome vazio");
}

resposta = x.setEmail('vaguetti@gmail.com');

console.log(resposta);

if (resposta) {
console.log(x.getEmail());
} else {
console.log("E-mail vazio");
}

// ===================================
console.log("==== Objeto PF =====");

const PF = require('./pessoas/PF');

const y = new PF();

resposta = y.setNome('Pedro');
console.log(resposta);

if (resposta) {
console.log(y.getNome());
} else {
console.log("Nome vazio");
}

resposta = y.setEmail('');
console.log(resposta);

if (resposta) {
console.log(y.getEmail());
} else {
console.log("Email vazio");
}

resposta = y.setCPF('123456789-10');
console.log(resposta);

if (resposta) {
console.log(y.getCPF());
} else {
console.log("CPF vazio");
}

// ===================================
console.log("==== Objeto PJ =====");

const PJ = require('./pessoas/PJ');

const z = new PJ();

resposta = z.setNome('Empresa ABC');
console.log(resposta);

if (resposta) {
console.log(z.getNome());
} else {
console.log("Nome vazio");
}

resposta = z.setEmail('contato@empresa.com');
console.log(resposta);

if (resposta) {
console.log(z.getEmail());
} else {
console.log("E-mail inválido");
}

resposta = z.setCNPJ('12.345.678/0001-90');
console.log(resposta);

if (resposta) {
console.log(z.getCNPJ());
} else {
console.log("CNPJ inválido");
}

📘 Comentários e Explicações Linha a Linha

Linhas 01--05

// Arquivo criado em projeto no www.stackblitz.com denominado usaPessoas.js
// Arquivo criado dentro de uma pasta /objetos na raiz do projeto
// Objetivo do exemplo: demonstrar a utilização dos conceitos de encapsulamento
// com adição de condicionais e Herança
// Classes Pessoa, PF e PJ disponíveis na pasta /objetos/pessoas

Esses comentários apresentam o objetivo do arquivo.

O arquivo usaPessoas.js é responsável por testar a criação e o uso dos objetos das classes Pessoa, PF e PJ.


Linha 07

console.log("==== Objeto Pessoa =====");

Exibe no terminal um título para identificar o início dos testes com a classe Pessoa.


Linha 09

const Pessoa = require('./pessoas/Pessoa');

Importa a classe Pessoa, permitindo criar objetos a partir dela.


Linha 11

const x = new Pessoa();

Cria um objeto chamado x a partir da classe Pessoa.

Esse processo é chamado de instanciação.


Linhas 13--14

// resposta = x.setNome('Leandro');
resposta = x.setNome('');

A linha 13 mostra um exemplo comentado de atribuição válida.

A linha 14 executa o método setNome() passando uma string vazia.

Como o valor está vazio, espera-se que o método retorne false.


Linha 16

console.log(resposta);

Exibe no terminal o valor retornado pelo método setNome().

Nesse caso, a saída esperada é:

false

Linhas 18--22

if (resposta) {
console.log(x.getNome());
} else {
console.log("Nome vazio");
}

Verifica o valor da variável resposta.

Como resposta é false, o bloco else será executado, exibindo:

Nome vazio

Linha 24

resposta = x.setEmail('vaguetti@gmail.com');

Executa o método setEmail() com um e-mail preenchido.

Como o valor não está vazio, a validação é aprovada.


Linha 26

console.log(resposta);

Exibe o retorno do método setEmail().

Nesse caso, espera-se:

true

Linhas 28--32

if (resposta) {
console.log(x.getEmail());
} else {
console.log("E-mail vazio");
}

Como resposta é true, o método getEmail() será chamado.

A saída esperada é:

vaguetti@gmail.com

Linhas 34--35

// ===================================
console.log("==== Objeto PF =====");

Separa visualmente os testes realizados com a classe Pessoa dos testes realizados com a classe PF.


Linha 37

const PF = require('./pessoas/PF');

Importa a classe PF, que representa uma Pessoa Física.

Essa classe herda métodos da classe Pessoa.


Linha 39

const y = new PF();

Cria um objeto chamado y a partir da classe PF.

Mesmo sendo um objeto da classe PF, ele também pode utilizar métodos herdados da classe Pessoa.


Linha 41

resposta = y.setNome('Pedro');

Executa o método setNome() no objeto y.

Esse método não foi declarado diretamente na classe PF, mas funciona porque foi herdado da classe Pessoa.


Linha 42

console.log(resposta);

Exibe o retorno do método setNome().

Como o nome informado é válido, espera-se:

true

Linhas 44--48

if (resposta) {
console.log(y.getNome());
} else {
console.log("Nome vazio");
}

Como a resposta foi true, o método getNome() será chamado.

A saída esperada é:

Pedro

Linhas 50--51

resposta = y.setEmail('');
console.log(resposta);

Executa o método setEmail() com uma string vazia.

Como o valor é inválido, espera-se que o retorno seja:

false

Linhas 53--57

if (resposta) {
console.log(y.getEmail());
} else {
console.log("Email vazio");
}

Como resposta é false, o bloco else será executado.

A saída esperada é:

Email vazio

Linhas 59--60

resposta = y.setCPF('123456789-10');
console.log(resposta);

Executa o método setCPF() da classe PF.

Esse método é específico da classe PF, pois o CPF é um atributo próprio de Pessoa Física.

Como o CPF foi informado, espera-se que o retorno seja:

true

Linhas 62--66

if (resposta) {
console.log(y.getCPF());
} else {
console.log("CPF vazio");
}

Como resposta é true, o método getCPF() será chamado.

A saída esperada é:

123456789-10

Linhas 68--69

// ===================================
console.log("==== Objeto PJ =====");

Separa visualmente os testes realizados com a classe PF dos testes realizados com a classe PJ.


Linha 71

const PJ = require('./pessoas/PJ');

Importa a classe PJ, que representa uma Pessoa Jurídica.

Essa classe também herda métodos da classe Pessoa, mas possui regras próprias para CNPJ e email.


Linha 73

const z = new PJ();

Cria um objeto chamado z a partir da classe PJ.

Esse objeto possui:

  • métodos herdados da classe Pessoa, como setNome() e getNome();
  • métodos próprios da classe PJ, como setCNPJ() e getCNPJ();
  • método sobrescrito, como setEmail().

Linhas 75--76

resposta = z.setNome('Empresa ABC');
console.log(resposta);

Executa o método setNome() no objeto z.

Esse método foi herdado da classe Pessoa.

Como o nome informado é válido, espera-se que o retorno seja:

true

Linhas 78--82

if (resposta) {
console.log(z.getNome());
} else {
console.log("Nome vazio");
}

Como resposta é true, o método getNome() será chamado.

A saída esperada é:

Empresa ABC

Linhas 84--85

resposta = z.setEmail('contato@empresa.com');
console.log(resposta);

Executa o método setEmail() no objeto z.

Nesse caso, o método executado é a versão sobrescrita na classe PJ.

O e-mail será considerado válido porque:

  • não está vazio;
  • contém o caractere @.

Linhas 87--91

if (resposta) {
console.log(z.getEmail());
} else {
console.log("E-mail inválido");
}

Como resposta é true, o método getEmail() será chamado.

A saída esperada é:

contato@empresa.com

Linhas 93--94

resposta = z.setCNPJ('12.345.678/0001-90');
console.log(resposta);

Executa o método setCNPJ() da classe PJ.

O CNPJ informado possui 18 caracteres, por isso será aceito pela validação.

A saída esperada para console.log(resposta) é:

true

Linhas 96--100

if (resposta) {
console.log(z.getCNPJ());
} else {
console.log("CNPJ inválido");
}

Como resposta é true, o método getCNPJ() será chamado.

A saída esperada é:

12.345.678/0001-90

📌 Conceitos-Chave Envolvidos


Conceito Explicação


require() Importa classes de outros arquivos.

new Cria uma nova instância de uma classe.

Objeto Estrutura criada a partir de uma classe.

Herança Permite que PF e PJ utilizem métodos da classe Pessoa.

Encapsulamento O acesso aos atributos ocorre por métodos set e get.

if/else Controla o fluxo com base no retorno dos métodos.

console.log() Exibe informações no terminal.

Método herdado Método definido em uma classe base e usado pela classe filha.

Método próprio Método declarado diretamente na classe específica.

Método sobrescrito Método herdado que foi redefinido na classe filha.


💡 Dicas do Professor

  • Teste primeiro a classe base antes de testar as classes filhas.
  • Separe os testes com mensagens no terminal para facilitar a leitura da saída.
  • Observe quais métodos são herdados e quais métodos pertencem somente à classe filha.
  • Utilize retornos true e false para controlar mensagens de erro e sucesso.
  • A classe PJ demonstra como uma classe filha pode adaptar o comportamento herdado por meio da sobrescrita.

💡 Resumo Final

Nesta apostila foram apresentados conceitos fundamentais da Programação Orientada a Objetos em JavaScript:

  • herança com extends;
  • criação de subclasses;
  • atributos privados com #;
  • encapsulamento com validação;
  • sobrescrita de métodos;
  • uso de super para chamar métodos da classe base;
  • operadores de comparação;
  • validação de strings com length e includes();
  • importação e exportação de módulos;
  • instanciação e utilização de objetos.

Esses conceitos permitem criar classes mais especializadas e com regras próprias, reaproveitando comportamentos já existentes em classes base.


📚 Exercícios de Fixação