Baixe o app para aproveitar ainda mais
Prévia do material em texto
© ELFS 47 • Como já sabemos, a primeira preocupação na POO deve ser identificar as classes que o programa precisa. • Em seguida, devemos pensar quais devem ser os campos e os métodos dessas classes (e, consequentemente, de seus objetos). • Vamos imaginar que um programa precisa tratar com datas (dia/mes/ano) e que para esse programa foi construída a seguinte classe: 3. Projeto de Classes: Campos e Métodos Data − int dia − int mes − int ano + Data() + Data(int, int, int) + void paraFrente(int) + void paraTras(int) + String toString() − boolean anoBissexto() − int diasDoMes() − void avancar() − void voltar() Algumas questões importantes são: • Por que os campos da classe são privados? • Uma classe pode ter campos públicos? • Por que alguns métodos são privados e outros são públicos? • Por que o método Data() não tem um tipo, como os demais métodos? • Por que existem dois métodos Data()? © ELFS 48 • Por que os campos são privados? Uma classe pode ter campos públicos? • Os campos devem ser privados para garantir que o estado de um objeto seja sempre consistente. Uma classe pode ter campos públicos, desde que não seja possível atribuir novos valores a esses campos (caso das constantes). 3. Projeto de Classes: Campos e Métodos d.dia = 32; // impossível Data + int dia + int mes + int ano d.dia = 32; // problema Data − int dia − int mes − int ano Com os campos privados o usuário não pode atribuir um valor (válido ou inválido) a um campo. Se for necessário atribuir um valor a um campo, esta atribuição deve ser feita por um método público da classe. Isso garante que a atribuição será sempre válida. public void setDia(int d) { if (d >= 1 && d <= diasDoMes()) dia = d; else System.out.println("Dia incorreto"); } © ELFS 49 • Os métodos públicos que atribuem valores aos campos privados da classe são conhecidos como setters. Esses métodos costumam ser declarados sempre como: setNomeDoCampo(tipo parâmetro) • Classe Data: 3. Projeto de Classes: Campos e Métodos Data − int dia − int mes − int ano public void setDia(int d) { if (d >= 1 && d <= diasDoMes()) dia = d; else System.out.println("Dia incorreto"); } public void setMes(int m) { if (m >= 1 && m <= 12) mes = m; else System.out.println("Mes incorreto"); } public void setAno(int a) { if (a >= 1) ano = a; else System.out.println("Ano incorreto"); } + void setDia() + void setMes() + void setAno() © ELFS 50 • Uma classe deve também incluir métodos públicos que retornam os valores atuais dos campos privados da classe. Esses métodos são conhecidos como getters e costumam ser declarados como: tipo getNomeDoCampo() • Classe Data: 3. Projeto de Classes: Campos e Métodos Data − int dia − int mes − int ano public int getDia() { return dia; } public int getMes() { return mes; } public int getAno() { return ano; } + void setDia() + void setMes() + void setAno() + int getDia() + int getMes() + int getAno() Observar que os getters garantem o acesso aos valores dos campos, uma vez que o acesso diretamente a um campo privado não é possível. d = dia; ERRADO! d = getDia(); CERTO! © ELFS 51 • Por que alguns métodos são privados e outros são públicos? • Uma classe pode ter campos e métodos privados ou públicos. • Campos: devem ser privados (para garantir a consistência dos objetos). • Campos públicos: no caso de constantes (valor não pode ser alterado). • Métodos: em geral, devem ser públicos (API da classe) • Métodos privados: quando são internos à classe (não estão na API) • Em geral, os campos e métodos de uma classe podem ser: onde (package) indica que nenhum modificador foi usado. 3. Projeto de Classes: Campos e Métodos Nível de acesso Modificador Classe Pacote Subclasse Todas public S S S S protected S S S N (package) S S N N private S N N N © ELFS 52 • Por que o método Data() não tem um tipo, como os demais métodos? E por que existem dois métodos Data()? • Porque, para a classe Data, o método Data() é um construtor. O objetivo de um método construtor é construir objetos da classe. • Os construtores são métodos especiais que têm o mesmo nome da classe e garantem que cada objeto da classe inicia sua existência em um estado consistente. • Construtores, como qualquer outro método, podem receber parâmetros. • Um construtor não retorna valor algum, nem mesmo do tipo void. • Toda classe deve ter um construtor. Se nenhum construtor for declarado no corpo da classe, um construtor padrão será incluído na compilação. Este construtor padrão não tem parâmetros e permite que se criem objetos de uma classe utilizando a instrução new Classe(). • Se em uma classe que não tinha um construtor explícito, for declarado um construtor, essa classe irá perder o construtor padrão. Se o construtor incluído tiver parâmetros, todas as chamadas posteriores a new Classe() causarão erros de compilação. Portanto, ao definir construtores em uma classe, deve-se sempre definir também um construtor sem parâmetros. 3. Projeto de Classes: Campos e Métodos • Exemplo. Vamos considerar a representação de um horário utiliza 3 campos inteiros: hor, min e seg. public class Horario { private int hor; private int min; private int seg; public Horario() { setHora(0); setMinuto(0); setSegundo(0); } public Horario(int h, int m, int s) { setHora(h); setMinuto(m); setSegundo(s); } © ELFS 53 3. Projeto de Classes: Campos e Métodos Horario.java Uma classe pode ter mais de um construtor. Os construtores devem chamar os setters para atribuir valores aos campos da classe. public int getHora() { return hor; } public int getMinuto() { return min; } public int getSegundo() { return seg; } public final void setHora(int h) { hor = (( h >= 0 && h < 24 )? h : 0); } public final void setMinuto(int m) { min = (( m >= 0 && m < 60 )? m : 0); } public final void setSegundo(int s) { seg = (( s >= 0 && s < 60 )? s : 0); } © ELFS 54 3. Projeto de Classes: Campos e Métodos Esses são os setters da classe. Observar que os setters devem ser sempre final void. Esses são os getters da classe. Observar que os getters são métodos que têm o mesmo tipo que o campo da classe a que se referem. © ELFS 55 @Override public String toString() { DecimalFormat df = new DecimalFormat("00"); return (df.format(getHora()) + ":" + df.format(getMinuto()) + ":" + df.format(getSegundo())); } } 3. Projeto de Classes: Campos e Métodos © ELFS 55 public class UsaHorario { public static void main(String[] args) { Horario h = new Horario(); System.out.println(h.toString()); h.setHora(15); h.setMinuto(30); System.out.println(h); h = new Horario(20,60,99); System.out.println(h); } } UsaHorario.java Note que o método toString() pode ficar implícito. © ELFS 56 • A classe UsaHorario utiliza a classe Horario. Ou seja, a classe UsaHorario é um usuário da classe Horario. • Os usuários de uma classe utilizam a parte pública da classe (a API da classe) e desconhecem como os campos e os métodos da classe foram implementados. • Exemplo: se, em vez de representar um horário por três valores inteiros (hor, min, seg), um horário for representado como o número de segundosdesde a zero-hora, os usuários poderiam utilizar os mesmos métodos públicos e obter os mesmos resultados sem se dar conta disso. É claro que os métodos teriam que ser reimplementados, considerando essa nova representação do horário. w • Se a implementação de uma classe é alterada, desde que a API da classe permaneça a mesma, o código- fonte dos usuários da classe não precisa ser alterado. Isso torna muito mais fácil modificar e distribuir sistemas. 3. Projeto de Classes: Campos e Métodos Horario − int hor − int min − int seg + Horario() + Horario(int h, int m, int s) + int getHora() + int getMinuto() + int getSegundo() + final void setHora() + final void setMinuto() + final void setSegundo() + String toString() © ELFS 57 Exemplo: 3. Projeto de Classes: Campos e Métodos public class Horario { private int tempo; public Horario() { setHora(0); setMinuto(0); setSegundo(0); } public Horario(int h, int m, int s) { setHora(h); setMinuto(m); setSegundo(s); } Horario.java Até aqui nada mudou, pois os construtores chamam os setters para atribuir o valor correto ao campo da classe. © ELFS 58 3. Projeto de Classes: Campos e Métodos public int getHora() { return (tempo/3600); } public int getMinuto() { return ((tempo - 3600*getHora())/60); } public int getSegundo() { return (tempo - 3600*getHora() - 60*getMinuto()); } public final void setHora(int h) { int hh = ((h >= 0 && h < 24)? h : 0); tempo = hh*3600 + getMinuto()*60 + getSegundo(); } public final void setMinuto(int m) { int mm = ((m >= 0 && m < 60)? m : 0); tempo = getHora()*3600 + mm*60 + getSegundo(); } public final void setSegundo(int s) { int ss = ((s >= 0 && s < 60)? s : 0); tempo = getHora()*3600 + getMinuto()*60 + ss; } A implementação dos getters e setters muda, pois estes métodos dependem de como são representados os campos da classe. public class UsaHorario { public static void main(String args[]) { Horario h = new Horario(); System.out.println(h.toString()); h.setHora(15); h.setMinuto(30); System.out.println(h); h = new Horario(20,60,99); System.out.println(h); } } © ELFS 59 3. Projeto de Classes: Campos e Métodos @Override public String toString() { DecimalFormat df = new DecimalFormat("00"); return (df.format(getHora()) + ":" + df.format(getMinuto()) + ":" + df.format(getSegundo())); } UsaHorario.java Como a API da classe não mudou, a mesma classe usuária anterior pode ser usada agora. O método toString() também continua inalterado, pois utiliza os getters. © ELFS 60 • Uma classe pode conter vários métodos com o mesmo nome, desde que as assinaturas dos métodos sejam diferentes. Isto é chamado de sobrecarga de método. • Assinatura: combinação do nome do método com sua lista de parâmetros. • Quando um método sobrecarregado é chamado, o compilador seleciona o método adequado examinando sua assinatura. • Em geral, os construtores de uma classe são métodos sobrecarregados. 3. Projeto de Classes: Campos e Métodos public int quadrado(int x) { return x * x; } public double quadrado(double x) { return x * x; } Assinatura: quadrado.int Assinatura: quadrado.double Se houvesse um outro método: public double quadrado(int z) o que ocorreria? © ELFS 61 3. Projeto de Classes: Campos e Métodos Exercício 1. Criar uma classe Retangulo com campos privados comprimento e largura. A classe deve ter métodos para calcular o perímetro e a área do retângulo. A classe deve conter os getters e setters necessários. Os setters devem verificar se os valores dos campos são válidos. Valores válidos são números de ponto flutuante no intervalo [1, 20]. O valor default deve ser 1. Exercício 2. Implementar a classe Data. A classe deve conter os getters e setters necessários. Os demais métodos da classe são tais que: • avancar(): deve avançar a data em 1 dia. • voltar(): deve retroceder a data em um 1 dia. • anoBissexto(): deve retornar true se ((ano % 100 <> 0) && (ano % 4 == 0)) || ((ano % 100 == 0) && (ano % 400 == 0)) • diasDoMes(): deve retornar o número de dias do mês, levando em conta se o ano é bissexto ou não. • paraFrente(int n): deve chamar avancar() n vezes. • paraTras(int n): deve chamar o método voltar() n vezes.
Compartilhar