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:
- Manter o nome simples e descritivo;
- Usar palavras inteiras, isto é, sem siglas e abreviações;
- 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.
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.