(→Classe "Aplication") |
|||
(24 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | + | {{TOCright}} | |
+ | O exemplo aqui apresentado ilustra o processo de especialização de uma classe por outra, de si derivada. Além do processo de especialização, o exemplo permite ver ainda aspectos como a iniciação de atributos '''final''' e a invocação explícita de construtores de superclasses (i.e., a sequência de iniciação de um objecto de uma classe derivada de outra). | ||
− | A | + | A aplicação exemplo ilustra ainda o processo de ''upcasting'', i.e., utilizar uma referência de um tipo mais geral que o do objecto que refere. |
− | São apresentados dois cenários para ilustrar o comportamento na iniciação de um atributo declarado | + | == Classe "SuperClasse" == |
+ | |||
+ | A classe '''SuperClasse''' representa o conceito mais geral, que irá ser posteriormente especializado. | ||
+ | |||
+ | São apresentados dois cenários para ilustrar o comportamento na iniciação de um atributo declarado '''final'''. | ||
=== Cenário A === | === Cenário A === | ||
− | No cenário A, o atributo é declarado, mas não tem um iniciador por omissão | + | No cenário A, o atributo é declarado, mas não tem um iniciador por omissão explícito. Por isso, é possível definir no construtor o seu valor. |
+ | <source lang="java"> | ||
public class SuperClasse { | public class SuperClasse { | ||
− | private | + | private int _a = 78; |
protected final int _x; // cenário A | protected final int _x; // cenário A | ||
Line 30: | Line 36: | ||
} | } | ||
+ | </source> | ||
=== Cenário B === | === Cenário B === | ||
− | No cenário | + | No cenário B, o atributo é declarado, mas já tem um iniciador por omissão explícito. Por isso, já não é possível definir no construtor o seu valor. |
− | + | <source lang="java"> | |
public class SuperClasse { | public class SuperClasse { | ||
private int _a = 78; | private int _a = 78; | ||
Line 56: | Line 63: | ||
} | } | ||
+ | </source> | ||
+ | |||
+ | == Classe "SubClasse" == | ||
+ | |||
+ | A classe '''SubClasse''' corresponde a uma especialização da superclasse e redefine o método '''getX'''. | ||
+ | |||
+ | Note-se a sintaxe de invocação do construtor da superclasse, utilizando a palavra chave '''super''': esta chamada é necessária, pois a não existência de um construtor sem argumentos na superclasse faz com que o comportamento por omissão do construtor da subclasse (na iniciação da porção do objecto correspondente à superclasse) não possa ser executado. | ||
+ | |||
+ | <source lang="java"> | ||
+ | public class SubClasse extends SuperClasse { | ||
+ | |||
+ | SubClasse() { | ||
+ | super(4); | ||
+ | System.out.println("-- calling SubClasse.SubClasse()"); | ||
+ | } | ||
+ | |||
+ | protected int getX() { | ||
+ | int result = 1 + super.getX(); | ||
+ | System.out.println("-- calling SubClasse.getX() returns " + result); | ||
+ | return result; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | |||
+ | == Aplicação Exemplo == | ||
+ | |||
+ | Note-se o processo de ''upcasting'' (em '''myD'''): a referência é para '''SuperClasse''' e o objecto é do tipo '''SubClasse'''. | ||
+ | |||
+ | === Classe "Aplication" === | ||
+ | |||
+ | Note-se que a chamada a '''getA''' ('''final''') é sempre executada fazendo do uso do código da superclasse (o facto de o método ser '''final''' impede a redefinição pelas subclasses). | ||
+ | <source lang="java"> | ||
+ | public class Aplication { | ||
+ | public static void main(String args[]) { | ||
+ | SuperClasse myS = new SuperClasse(8); // ok: mesmo tipo | ||
+ | SuperClasse myD = new SubClasse(); // ok: upcasting | ||
+ | System.out.println("in main: myS.getA() = " + myS.getA()); | ||
+ | System.out.println("in main: myS.getX() = " + myS.getX()); | ||
+ | System.out.println("in main: myD.getA() = " + myD.getA()); | ||
+ | System.out.println("in main: myD.getX() = " + myD.getX()); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | === Saída da Aplicação === | ||
+ | |||
+ | $ '''java Aplication''' | ||
+ | |||
+ | -- calling SuperClasse.SuperClasse(8) | ||
+ | -- calling SuperClasse.SuperClasse(4) | ||
+ | -- calling SubClasse.SubClasse() | ||
+ | -- calling SuperClasse.getA() returns 46 | ||
+ | in main: myS.getA() = 46 | ||
+ | -- calling SuperClasse.getX() returns 8 | ||
+ | in main: myS.getX() = 8 | ||
+ | -- calling SuperClasse.getA() returns 9 | ||
+ | in main: myD.getA() = 9 | ||
+ | -- calling SuperClasse.getX() returns 4 | ||
+ | -- calling SubClasse.getX() returns 5 | ||
+ | in main: myD.getX() = 5 | ||
+ | |||
− | + | [[category:PO]] | |
+ | [[category:PO Exemplos]] | ||
+ | [[category:Ensino]] |
O exemplo aqui apresentado ilustra o processo de especialização de uma classe por outra, de si derivada. Além do processo de especialização, o exemplo permite ver ainda aspectos como a iniciação de atributos final e a invocação explícita de construtores de superclasses (i.e., a sequência de iniciação de um objecto de uma classe derivada de outra).
A aplicação exemplo ilustra ainda o processo de upcasting, i.e., utilizar uma referência de um tipo mais geral que o do objecto que refere.
A classe SuperClasse representa o conceito mais geral, que irá ser posteriormente especializado.
São apresentados dois cenários para ilustrar o comportamento na iniciação de um atributo declarado final.
No cenário A, o atributo é declarado, mas não tem um iniciador por omissão explícito. Por isso, é possível definir no construtor o seu valor.
public class SuperClasse {
private int _a = 78;
protected final int _x; // cenário A
SuperClasse(int x) {
System.out.println("-- calling SuperClasse.SuperClasse(" + x + ")");
_a = (int)(100*Math.random());
_x = x; // ok: cenário A
}
final int getA() {
System.out.println("-- calling SuperClasse.getA() returns " + _a);
return _a;
}
protected int getX() {
System.out.println("-- calling SuperClasse.getX() returns " + _x);
return _x;
}
}
No cenário B, o atributo é declarado, mas já tem um iniciador por omissão explícito. Por isso, já não é possível definir no construtor o seu valor.
public class SuperClasse {
private int _a = 78;
protected final int _x = 93; // iniciação
SuperClasse(int x) {
System.out.println("-- calling SuperClasse.SuperClasse(" + x + ")");
_a = (int)(100*Math.random());
//_x = x; // erro: já está iniciada
}
final int getA() {
System.out.println("-- calling SuperClasse.getA() returns " + _a);
return _a;
}
protected int getX() {
System.out.println("-- calling SuperClasse.getX() returns " + _x);
return _x;
}
}
A classe SubClasse corresponde a uma especialização da superclasse e redefine o método getX.
Note-se a sintaxe de invocação do construtor da superclasse, utilizando a palavra chave super: esta chamada é necessária, pois a não existência de um construtor sem argumentos na superclasse faz com que o comportamento por omissão do construtor da subclasse (na iniciação da porção do objecto correspondente à superclasse) não possa ser executado.
public class SubClasse extends SuperClasse {
SubClasse() {
super(4);
System.out.println("-- calling SubClasse.SubClasse()");
}
protected int getX() {
int result = 1 + super.getX();
System.out.println("-- calling SubClasse.getX() returns " + result);
return result;
}
}
Note-se o processo de upcasting (em myD): a referência é para SuperClasse e o objecto é do tipo SubClasse.
Note-se que a chamada a getA (final) é sempre executada fazendo do uso do código da superclasse (o facto de o método ser final impede a redefinição pelas subclasses).
public class Aplication {
public static void main(String args[]) {
SuperClasse myS = new SuperClasse(8); // ok: mesmo tipo
SuperClasse myD = new SubClasse(); // ok: upcasting
System.out.println("in main: myS.getA() = " + myS.getA());
System.out.println("in main: myS.getX() = " + myS.getX());
System.out.println("in main: myD.getA() = " + myD.getA());
System.out.println("in main: myD.getX() = " + myD.getX());
}
}
$ java Aplication -- calling SuperClasse.SuperClasse(8) -- calling SuperClasse.SuperClasse(4) -- calling SubClasse.SubClasse() -- calling SuperClasse.getA() returns 46 in main: myS.getA() = 46 -- calling SuperClasse.getX() returns 8 in main: myS.getX() = 8 -- calling SuperClasse.getA() returns 9 in main: myD.getA() = 9 -- calling SuperClasse.getX() returns 4 -- calling SubClasse.getX() returns 5 in main: myD.getX() = 5