Uma classe é um elemento do código Java que utilizamos para representar objetos do mundo real. Dentro dela é comum declararmos atributos e métodos, que representam, respectivamente, as características e comportamentos desse objeto. Neste documento será apresentado como declarar e utilizar uma classe em Java.

Sintaxe

A declaração de uma classe em Java é bastante simples. Utilizamos a palavra reservada class seguida pelo nome da classe. Logo após, entre chaves, definimos os elementos a ela relacionados: atributos, construtores e métodos. Sintaxe de declaração de classe:

<modificador de acesso> class NomeDaClasse {
 
  // Local onde atributos, construtores e métodos são criados
 
}

Note que também é possível especificar o modificador de acesso. Por meio dele informamos a visibilidade da classe, que pode ser public, private ou default.

Exemplo de declaração de classe:

public class Produto {
 
  private String nome;
  private int quantidade;
 
  public Produto() {
    // Código do construtor
  }
 
  public void apresentarProduto() {
    // Código do método
  }
 
}

Este exemplo apresenta o código da classe Produto. Como foi declarada como public, poderá ser utilizada por todas as classes do projeto. Além disso, ela possui dois atributos (nome e quantidade), um construtor sem argumentos e um método.

Regras para nomeação de classes

Ao nomear uma classe algumas convenções devem ser seguidas:

  1. Manter o nome simples e descritivo;
  2. Usar palavras inteiras, isto é, sem siglas e abreviações;
  3. A primeira letra de cada palavra deve estar em caixa alta.

Como utilizar

Para utilizar uma classe devemos declará-la da mesma maneira que se declara uma variável de tipo primitivo. Declaramos o tipo (neste caso o nome da classe) seguido pelo nome da variável.

Exemplo de instanciação de classe:

  Produto produtoUm;
  produtoUm = new Produto();
  produtoUm.apresentarProduto();
  

A segunda linha deste código representa o processo de instanciação de uma classe. Na linha anterior, a variável produtoUm foi definida como sendo do tipo Produto. Em seguida, com a palavra reserva new, um espaço é criado na memória para armazenar um novo objeto do tipo Produto. O construtor Produto() especifica como o objeto deve ser criado. Por fim, uma referência a esse objeto é atribuída à variável produtoUm.

Assim, através de produtoUm podemos acessar o objeto criado (e seus atributos e métodos). Na terceira linha, por exemplo, utilizando a variável, acessamos o objeto e chamamos o método apresentarProduto().

Apesar do exemplo acima, o código para criar um objeto e definir a variável que conterá sua referência normalmente é declarado em apenas uma linha.

Exemplo de instanciação de classe:

Produto produtoUm = new Produto();

Extends

Quando uma classe precisa herdar características de outra, fazemos uso de herança, conceito da orientação a objetos que em Java é representado pela palavra-chave extends.

Sintaxe de declaração de herança:

  public class MinhaClasse extends ClasseQualquer {
   
  }
  

Com extends, todos os atributos e métodos não-privados de ClasseQualquer serão herdados por MinhaClasse. Por isso, é comum dizer que a classe herdada (ClasseQualquer) é pai da classe que herdou seus elementos (MinhaClasse).

Exemplo de herança em Java:

  public class Produto {
   
    public double valorCompra;
    protected double valorVenda;
   
  }
   
  public class Computador extends Produto {
   
     private String processador;
   
  }

Note que a palavra-chave extends foi utilizada na declaração da classe Computador. Assim, além do atributo processador, devido à herança, a classe Computador também terá os atributos valorCompra e valorVenda, sem que seja necessário declará-los novamente, sem repetir código.

Nota: Em Java não existe herança múltipla. Assim, uma classe pode herdar apenas de outra.

Implements

Quando uma classe precisa implementar os métodos de uma interface, utiliza-se a palavra reservada implements:

public class MinhaClasse implements NomeInterface {

}

Ao utilizar implements a classe passa a ser obrigada a implementar os métodos da interface.

Exemplo de uso:

  public interface IProduto {
   
       public double calculaFrete();
   
  }
   
   
  public class Televisao implements IProduto {
   
       private double peso;
       private double altura;
   
       @Override
       public double calculaFrete() {
          //código para cálculo do frete
       }
   
       public double getPeso() {
         return peso;
       }
   
       public void setPeso(double peso) {
         this.peso = peso;
       }
   
       public double getAltura() {
         return altura;
       }
   
       public void setAltura(double altura) {
         this.altura = altura;
       }
   
  }
  

Como a classe Televisao implementa a interface IProduto, precisa implementar o método calcularFrete(). A anotação @override explicita os métodos que foram codificados/sobrescritos.

Diferentemente do que acontece quando utilizamos a herança, podemos implementar várias interfaces. Para isso, basta separá-las por vírgula.

Exemplo de classe que implementa várias interfaces:

  public class Televisao implements Produto, Eletronico  {
   
     //Campos, construtores e métodos da classe Televisao
 
     //Implementação dos métodos da interface Produto
    
     //Implementação dos métodos da interface Eletronico
  }

Também é possível utilizar extends conjuntamente com implements. Trata-se de um recurso útil quando deseja-se tornar uma classe mais específica e implementar novos comportamentos definidos em interfaces.

Exemplo de uso:

  public class ClasseFilha extends ClassePai implements NomeInterface {
   
     // Atributos, construtores e métodos da ClasseFilha
   
     //Métodos implementados da interface
   
  }
  

Exemplo prático

Suponha que você precisa criar uma classe para representar os funcionários de uma empresa que ocupam o cargo de editor. Como você faria isso sabendo que já existe uma classe de nome Funcionario, apresentada a seguir, que define as características comuns a todo funcionário? Simples, você pode utilizar herança.

public class Funcionario {
   
  private String nome;
  private Long salario;
   
  public Funcionario() { 
  }
   
  public Funcionario(String nome, Long salario) {
    this.nome = nome;
    this.salario = salario;
  }
   
  public void trabalhar() {
    System.out.println(“Estou trabalhando!”); 
  }
   
  public String getNome() {
    return nome;
  }
   
  public void setNome(String nome) {
    this.nome = nome;
  }
   
  public Long getSalario() {
    return salario;
  }
     
  public void setSalario(Long salario) {
    this.salario = salario;
  }

}

Na classe Funcionario declaramos dois atributos: nome, do tipo String; e salario, do tipo Long. Com isso, indicamos que o atributo nome pode armazenar valores alfanuméricos e o atributo salario, apenas números. Observe, também, que ambos foram declarados com o modificador de acesso private. Fazemos isso para manter o encapsulamento. A partir disso, para alterar e acessar os valores desses atributos, é preciso utilizar os métodos de acesso, os getters e setters.

Declaramos, em seguida, dois construtores, sendo um padrão - sem parâmetros - e outro com a capacidade de instanciar um funcionário com todas as informações a ele relacionadas.

Logo após, programamos o método trabalhar(), o qual representa o trabalho sendo desempenhado pelo funcionário. Por fim, você pode notar a implementação dos métodos de acesso.

Solução do exemplo:

public class Editor extends Funcionario {
   
  @Override 
  public void trabalhar() {
     System.out.println(“Estou trabalhando como editor!”);
     editarVideo();
  }

  public void editarVideo() {
     //Código do método para edição do vídeo.   
  }

}

Com a palavra-chave extends, Editor herdará todos os atributos de Funcionario – neste caso, nome e salario – assim como o método trabalhar(). Portanto, devido à herança, não é necessário repetir esses atributos na classe Editor, e, também por isso, dizemos que Editor é uma classe filha de Funcionario.

Além disso, como a forma de trabalho dos editores é diferente da forma de trabalho dos demais funcionários, note que sobrescrevemos o método trabalhar() com um código equivalente ao cargo a ele relacionado. Para reforçar a sobrescrita do método trabalhar(), utilizamos a anotação @Override.

Note, por fim, que ajustamos o que estava em System.out.println() e, logo após essa linha, chamamos o método editarVideo(), que representa uma função desempenhada apenas por funcionários que ocupam o cargo de Editor.