Extensão de classes em Java - noções elementares - PCO / PPO Departamento de Informática Faculdade de Ciências da Universidade de Lisboa
Conteúdo Noções elementares de extensão de classes Exemplo: classe TimeOfDaySecs Declaração de subclasse usando extends. Implementação de construtores. Extensão, herança e reutilização de funcionalidade. Redefinição de métodos. Referência à super-classe com super. Restrições à herança com final. A anotação @Override. 2
Extensão de classes??? public class TimeOfDaySecs... { public TimeOfDaySecs(int h, int m, int s) { public int getseconds() { public void setseconds(int s) { public String tostring() { Exemplo introdutório: definição da classe TimeOfDaySecs por extensão da classe TimeOfDay TimeOfDaySecs estende a funcionalidade de TimeOfDay, representando a hora do dia com a precisão de segundos. 3
extends public static final int SECONDS_PER_MINUTE = 60; public TimeOfDaySecs(int h, int m, int s) { public int getseconds() { public void setseconds(int s) { public String tostring() { A relação de herança entre classes em Java é definida por pelo uso da palavra-chave extends na declaração de uma classe. No exemplo: TimeOfDaySecs, designada por subclasse, estende TimeOfDay, designada por super-classe. 4
Hierarquia de classes package java.lang; public class Object { package pco.time; public class TimeOfDay { Uma classe pode estender uma e uma só super-classe. Não podemos declarar mais do que uma super-classe com extends. Por omissão a super-classe é java.lang.object (extends java.lang.object implícito em TimeOfDay), de que iremos falar nas próximas aulas Apenas java.lang.object não tem super-classe: é a classe raiz da hierarquia de objectos em Java. 5
TimeofDaySecs campos de instância private int seconds; public TimeOfDaySecs(int h, int m, int s) { A classe TimeOfDay já representa o tempo em horas e minutos Declaramos em TimeOfDaySecs apenas um campo de instância (seconds) para representar adicionalmente os segundos. 6
TimeofDaySecs - construtor private int seconds; //@ requires h >= 0 && h < HOURS_PER_DAY //@ requires m >= 0 && m < MINUTES_PER_HOUR //@ requires s >= 0 && s < SECONDS_PER_MINUTE public TimeOfDaySecs(int h, int m, int s) { super(h, m); // Call superclass constructor. seconds = s; // Initialize value for seconds. Este construtor de TimeOfDaySecs inicializa o objecto em dois passos: A invocação de um construtor da classe-pai TimeOfDay. Inicialização do valor dos segundos (seconds). A palavra-chave super é usada para referência à super-classe. Um construtor de uma subclasse começa sempre por invocar o construtor da super-classe. 7
package java.lang; public class Object { public Object () { public class TimeOfDay { private int hours; private int minutes; public TimeOfDay(int h, int m) { super(); hours = h; minutes = m; Obs: super() implícito quando omitido) private int seconds; public TimeOfDaySecs(int h, int m, int s) { super(h, m); seconds = s; TimeOfDaySecs t = new TimeOfDaySecs(12, 30, 59); 8
Definição de nova funcionalidade em subclasses private int seconds; public TimeOfDaySecs(int h, int m, int s) { public int getseconds() { return seconds; //@ requires s >= 0 && s < SECONDS_PER_MINUTE public void setseconds(int s) { seconds = s; Podemos definir agora nova funcionalidade na subclasse getseconds() / setseconds() no exemplo 9
Herança de métodos public class TimeOfDay { public int gethours() { return hours; public int getminutes() { return minutes; public int getseconds() { return seconds; TimeOfDaySecs t = new TimeOfDaySecs(12, 30, 59); int h = t.gethours(); int m = t.getminutes(); int s = t.getseconds(); e reutilizar funcionalidade da super-classe 10
Reutilização de funcionalidade public void advanceonesecond() { seconds ++; if (seconds == SECONDS_PER_MINUTE) { advanceoneminute(); // in TimeOfDay public class TimeOfDay { public void advanceoneminute() { minutes ++; if (minutes == MINUTES_PER_HOUR) { minutes = 0; advanceonehour(); advanceonesecond e m TimeOfDaySecs c h a m a advanceoneminute em TimeOfDay 11
Redefinição de métodos tostring - versão 1 public class TimeOfDay { public String tostring() {. HH:MM public String tostring() { StringBuilder sb = new StringBuilder(); if (gethours() < 10) sb.append('0'); sb.append(gethours()); sb.append(':'); if (getminutes() < 10) sb.append('0'); sb.append(getminutes()); sb.append(':'); if (seconds < 10) sb.append('0'); sb.append(seconds); return sb.tostring(); Método tostring redefinido em TimeOfDaySecs HH:MM:SS 12
Redefinição de métodos (tostring) - versão 2 public class TimeOfDay { public String tostring() {. HH:MM public String tostring() { // Call TimeOfDay.toString(). String hhmm = super.tostring(); StringBuilder sb = new StringBuilder(hhmm); sb.append(':'); if (seconds < 10) sb.append('0'); sb.append(seconds); return sb.tostring(); tostring() chama implementação da super-classe HH:MM:SS 13
Anotação @Override package java.lang; public class Object { public String tostring() { public class TimeOfDay { @Override public String tostring() { @Override public String tostring() { Boa prática: A anotação opcional @Override assinala uma redefinição de método. Previne erros de programação (ex. se chamarmos ao método tostring em vez de tostring não teremos uma redefinição). 14
Restrições à redefinição de métodos public class TimeOfDay { public final int gethours() { public final void sethours(int h) { public final int getminutes() { public final void setminutes(int m) { Devemos identificar com final os métodos que não poderão ser redefinidos por subclasses. Não seria boa ideia/prática redefinir gethours() etc em TimeOfDaySecs conseguimos restringir essa redefinição usando o modificador final. 15
Restrições à definição de subclasses public class TimeOfDay { public final int gethours() { public final void sethours(int h) { public final int getminutes() { public final void setminutes(int m) { public final class TimeOfDaySecs extends TimeOfDay { Por outro lado podemos aplicar final à classe TimeOfDaySecs para impedir que esta seja estendida. Nesse caso, nenhuma classe poderá ter TimeOfDaySecs como super-classe. Exemplo na API do Java: java.lang.string 16