Programação por Objectos Java

Propaganda
Programação por Objectos
Java
Parte 6: Herança e Polimorfismo
LEEC@IST
Java – 1/52
Herança – revisão
• A herança é um mecanismo em que a subclasse
constitui uma especialização da superclasse. A
superclasse pode ser vista como generalização das
subclasses.
• A herança é dita como uma relação “is-a”.
• As subclasses herdam os atributos e métodos das
superclasses. Os métodos herdados podem ser
modificados. Novos atributos e métodos podem ser
adicionados às subclasses.
LEEC@IST
Java – 2/52
Herança – revisão
• O polimorfismo ocorre quando há múltipla
definição, ou redefinição, de métodos da
superclasse nas subclasses, com a mesma
assinatura.
• Em OO o polimorfismo é normalmente implementado
através de ligação dinâmica, i.e., o método a ser
executado é determinado apenas em tempo de
execução (e não em tempo de compilação).
LEEC@IST
Java – 3/52
Herança – revisão
• Na herança simples cada subclasse tem
apenas uma superclasse (directa).
• Na herança múltipla uma subclasse pode ter
mais do que uma superclasse (directa).
LEEC@IST
Java – 4/52
Herança (1)
•
O Java adopta as seguintes estratégias na herança:
– Só há herança simples de classes.
– Todas as classes são subclasses de Object (explícita ou
implicitamente).
– A subclasse herda todos os atributos e métodos das
superclasses.
•
Os construtores não são métodos, e por isso não são
herdados.
– Os atributos private não são visiveis na subclass, os
atributos protected e public mantem a mesma
visibilidade.
•
LEEC@IST
No caso de atributos e métodos sem qualificador de visibilidade
(visibilidade de pacote), a subclasse herda estes atributos e
métodos se estiver definida no mesmo pacote que a
superclasse, e apenas neste caso.
Java – 5/52
Herança (2)
– Se a subclasse declarar um método com o
mesmo identificador e parâmetros (número e tipo)
que uma das superclasses, então a subclasse
redefine esse método.
– Se a subclasse declarar um atributo com o
mesmo identificador que uma das superclasses,
então o atributo da subclasse esconde o
atributo da superclasse (mas continua a existir!)
LEEC@IST
Java – 6/52
Herança (3)
Sintaxe
Qualif* class Ident
[ extends IdentC] [ implements IdentI [,IdentI]* ] {
[ Atributos | Métodos ]*
}
•
•
•
•
Qualif: qualificador (visibilidade, entre outros)
Ident: identificador da classe
extends IdentC: especialização de superclasse
implements IdentI: realização de interfaces
LEEC@IST
Java – 7/52
Herança (4)
public class ContaPrazo extends Conta {
private static float juro=0.05;
private long inicio;
private int intervalo;
public void vencimentoJuros() {
long today = System.currentTimeMillis();
if(today==inicio+intervalo) {
quantia *= (1+juro);
inicio = today;
}
}
}
LEEC@IST
Java – 8/52
Construtores em subclasses (1)
•
•
•
•
•
É da responsabilidade da subclasse inicializar os atributos
definidos na sua classe, assim como os atributos que herda das
suas superclasses.
O construtor da subclasse pode delegar a inicialização dos
atributos herdados para a superclasse, chamando, implicita ou
explicitamente, o construtor da superclasse.
Um construtor da subclasse pode fazer uma chamada explícita
dum construtor da superclasse através do super().
Se o construtor da superclasse tiver N parâmetros, estes devem
ser passados na chamada explícita:
super(param1,...,paramN).
Se existir, a chamada explícita do construtor da superclasse
deve ser a primeira instrução no construtor.
LEEC@IST
Java – 9/52
Construtores em subclasses (2)
• Pode se chamar outro construtor da classe usando o
this(parametros).
• Se nenhum construtor da superclasse é chamado, ou
se nenhum construtor da classe é chamado, como
primeira instrução do construtor, o construtor sem
argumentos da superclasse é implicitamente
chamado antes de qualquer instrução no construtor.
• Se a superclasse não tiver um construtor sem
argumentos, é necessário chamar explicitamente um
construtor da superclasse.
– Note que um construtor implícito é
automaticamente criado se não existir mais
nenhum construtor, mas apenas neste caso.
LEEC@IST
Java – 10/52
Construtores em subclasses (3)
public class A {
protected int a;
A() {
a = 5;
}
A(int var) {
a = var;
}
}
Não é necessário chamar
explicitamente super()
pois super() é
implicitamente chamado!
LEEC@IST
public class DuplicaA extends A {
DuplicaA () {
a *= 2;
}
DuplicaA (int var) {
super(var);
a *= 2;
}
}
Java – 11/52
Construtores em subclasses (4)
public class A {
protected int número;
A(int num) {
número=num;
}
public class B extends A {
}
protected String nome=“não-definido”;
B() {
super(-1);
}
É necessário
B(int num) {
chamar
super(num);
explicitamente
}
super(-1) pois a
B(int num, String str) {
this(num);
superclasse não
nome = str;
tem construtor
}
sem argumentos!
}
LEEC@IST
Java – 12/52
Construtores em subclasses (5)
•
•
•
Quando um objecto é criado, é afectada memória para todos os
seus atributos, incluindo os herdados das superclasses.
Os atributos são inicializados com um valor por omissão,
dependendo do seu tipo.
Após isto a construção tem 3 fases:
1. Chamar o construtor da superclasse (através de uma
chamada implícita ou explícita).
•
•
•
LEEC@IST
Se uma chamada a this(parametros) é encontrada
então esta é efectuada e o processo reinicia-se no novo
construtor.
Se houver uma chamada super(parametros) é
encontrada então é chamado o construtor da super classe
correspondente. Caso contrário e chamado o constructor
por defeito da super class.
Este processo é repetido até chegar a object.
Java – 13/52
Construtores em subclasses (6)
•
Nesta fase, qualquer expressão que é passada como
argumento ao construtor explícito não deve incluir nem
atributos nem métodos do objecto a ser criado.
2. Inicializar os atributos (inicialização na declaração dos
mesmos e através de blocos de inicialização).
•
Nesta fase, referências para outros membros do objecto a ser
criado são permitidas, desde que estas já tenham sido
declaradas.
3. Chamar o corpo do construtor.
LEEC@IST
Java – 14/52
Construtores em subclasses (7)
•
Quando é criado um objecto do tipo B…
public class A {
protected int a=1;
protected int total;
A() {
total=a;
}
}
public class B extends A {
protected int b=2;
B () {
total+=b;
}
}
1. Atributos com valores por omissão
2. Construtor de B é chamado
3. Constructor de A é chamado (super())
4. Construtor Object é chamado
5. Inicialização dos atributos de A
6. Execução do construtor de A
7. Inicialização dos atributos de B
8. Execução do construtor de B
LEEC@IST
a
0
0
0
0
1
1
1
1
b
0
0
0
0
0
0
2
2
total
0
0
0
0
0
1
1
3
Java – 15/52
Herança e redefinição
• Numa classe derivada podem:
– ser adicionados novos atributos e métodos à classe.
– ser redefinidos métodos na classe.
LEEC@IST
Java – 16/52
Herança e redefinição
• Um método da subclasse é considerado uma
redefinição dum método da superclasse se:
– Ambos têm o mesmo identificador e parâmetros
(número e tipo).
– O tipo de retorno é covariante:
•
•
LEEC@IST
Se o tipo de retorno é uma referência, então o método
redefinido pode declarar como tipo de retorno um
subtipo do tipo de retorno do método da superclasse.
Se o tipo de retorno é um tipo primitivo, então o tipo
de retorno do método redefinido tem que ser idêntico
ao tipo de retorno do método da superclasse.
Java – 17/52
Herança e redefinição
• Um método só pode ser redefinido na subclasse
se for visível da superclasse para a subclasse.
– Se um método definido na superclasse não é visível na
subclasse então não é herdado.
– Se um método não é herdado, mesmo que um método com
o mesmo identificador, mesmos parâmetros (número e tipo)
e retorno covariante seja definido na subclasse, este método
não é uma redefinição do método na superclasse.
LEEC@IST
Java – 18/52
Herança e redefinição
• A visibilidade dos métodos redefinidos pode ser
diferente da dos métodos da superclasse, mas
apenas para dar mais acesso.
– Por exemplo, um método declarado na superclasse como
protected pode ser redefinido protected ou public, mas
não private ou com visibilidade de pacote.
LEEC@IST
Java – 19/52
Herança e redefinição
• Um método de instância não pode ter o mesmo
identificador tipo e número de parâmetros que
um método estático herdado, e vice-versa, ou
seja não podemos passar um método para
estático ou não estático.
• Um método redefinido pode ser declarado
abstracto, mesmo que o método da superclasse
não o seja.
LEEC@IST
Java – 20/52
Herança e redefinição
• A propriedade final dos parâmetros dum método
duma superclasse, pode ser retirada ou colocada
num método redefinido (trata-se apenas um
detalhe de implementação).
• Um método redefinido pode ser declarado final,
mas obviamente o método na superclasse não o
poderia ser.
LEEC@IST
Java – 21/52
Herança e redefinição
• A redefinição de métodos que substituem uma
sequência de parâmetros por uma tabela é possível,
mas é desanconselhável.
– Um método de argumento variável, com uma sequência de
parâmetros T…, tem a mesma assinatura que um método
que converte essa última sequência de parâmetros na
tabela T[].
LEEC@IST
Java – 22/52
Herança e redefinição
• Se um método definido numa subclasse tiver
– o mesmo identificador,
– mas diferente número ou tipo de parâmetros,
que um método (visível) da superclasse então é uma
sobreposição.
• Se um método definido numa subclasse tiver
– o mesmo identificador,
– mesmos número e tipo de parâmetros,
– mas o retorno não for covariante
relativamente a um método (visível) da superclasse
então existe um erro de compilação.
LEEC@IST
Java – 23/52
Herança e redefinição
• Um atributo da superclasse que é declarado na
subclasse com o mesmo nome (independentemente
do tipo) é escondido.
– Não há redefinição de atributos, estes são sempre
escondidos.
– O atributo da superclasse continua a existir, mas
deixa de ser possível à subclasse aceder-lhe
directamente.
– É necessário usar a referência super, ou outra
referência para o objecto da superclasse, para
aceder ao atributo escondido.
LEEC@IST
Java – 24/52
Polimorfismo
• Numa hierarquia de classes, quando há redefinição de
um método a sua implementação é substituída.
– Na presença de uma referência para um objecto na hierarquia
de classes, a chamada sobre esse objecto ao método
redefinido refere-se ao método de que classe?
• Quando um método é chamado através de uma
referência para um objecto, a classe de
instânciação do objecto (não necessariamente a
classe de declaração) dita a implementação a ser
usada.
SuperClasse sub = new SubClasse();
classe de declaração de sub
LEEC@IST
classe de instanciação de sub
Java – 25/52
Polimorfismo
• A classe de declaração de um objecto é
determinada em tempo de compilação.
– O compilador tem acesso a essa informação na própria
declaração da referência.
Conta conta = new ContaOrdem();
Conta conta;
...
//num outro ponto do programa
conta = new ContaOrdem();
LEEC@IST
Java – 26/52
Polimorfismo
• A classe de instânciação de um objecto é
determinada apenas em tempo de execução.
– A classe de instânciação pode sempre ser de uma classe
mais abaixo na hierarquia, relativamente à classe
declarada.
– A instanciação de um objecto pode ser feita num ponto do
programa completamente diferente do ponto onde a
declaração foi feita.
– Apenas o fluxo do programa dirá qual a classe de
instanciação.
Conta conta;
...
//num outro ponto do programa
Conta = new ContaOrdem();
LEEC@IST
Java – 27/52
Polimorfismo
public class Conta {
protected String str = “Conta”;
public void imprime() {
System.out.println(“ComtaImprime(): “+str);
}
}
public class ContaOrdem extends Conta {
protected String str = “ContaOrdem”;
public void imprime() {
System.out.println(“ContaOrdemImprime(): “+str);
}
LEEC@IST
Java – 28/52
Polimorfismo
//... Continuação do slide anterior
public static void main(String[] args) {
ContaOrdem contaOrdem = new ContaOrdem();
Conta conta = contaOrdem;
conta.imprime();
contaOrdem.imprime();
System.out.println(“conta.str = “+conta.str);
System.out.println(
“contaOrdem.str = ”+contaOrdem.str
);
}
}
No terminal é impresso:
Notar que os métodos são redefinidos
mas não os atributos
LEEC@IST
ContaOrdemImprime(): ContaOrdem
ContaOrdemImprime(): ContaOrdem
conta.str = Conta
contaOrdem.str = ContaOrdem
Java – 29/52
Polimorfismo
• Relativamente ao slide anterior:
– A classe de declaração e instanciação de contaOrdem é
contaOrdem.
• contaOrdem é tipo contaOrdem.
• contaOrdem contem um objecto contaOrdem.
– A classe de declaração de conta é Conta mas a
instanciação de conta é contaOrdem.
• conta é tipo conta.
• Conta contem um objecto contaOrdem definido em memória.
LEEC@IST
Java – 30/52
Polimorfismo
• Exemplo:
– num jogo existem três objectos Nave, Asteróide e Meteoro.
Para uma das nove colisões possíveis pretende-se chamar
um método diferente, determinado em tempo de
compilação:
Public abstract Classe ObjectoJogo {
abstract colisão(ObjectoJogo outro);
}
LEEC@IST
Java – 31/52
Polimorfismo
Public abstract Classe Nave {
colisão(ObjectoJogo outro){ outro.colisãoComNave(this);}
colisãoComNave(Nave outro){ … }
colisãoComAsteroide(Asteroide outro){ … }
colisãoComMeteoro(Meteoro outro){ … }
}
Public abstract Classe Asteroide {
colisão(ObjectoJogo outro){ outro.colisãoComAsteroide(this);}
colisãoComNave(Nave outro){ … }
colisãoComAsteroide(Asteroide outro){ … }
colisãoComMeteoro(Meteoro outro){ … }
}
Public abstract Classe Meteoro {
colisão(ObjectoJogo outro){ outro.colisãoComMeteoro(this);}
colisãoComNave(Nave outro){ … }
colisãoComAsteroide(Asteroide outro){ … }
colisãoComMeteoro(Meteoro outro){ … }
}
LEEC@IST
Java – 32/52
Referência super (1)
• A referência super está disponível em todos os
métodos de instância duma subclasse.
• No acesso a atributos e chamada de métodos, a
referência super funciona como uma referência
vista como uma instância da superclasse.
• A chamada super.método usa sempre a
implementação do método da superclasse (definido
ou herdado).
LEEC@IST
Java – 33/52
Referência super (2)
public class SuperClasse {
protected void nome() {
System.out.println(“SuperClasse”);
}
}
public class SubClasse extends SuperClasse {
protected void nome() {
System.out.println(“SubClasse”);
}
LEEC@IST
Java – 34/52
Referência super (3)
//... Continuação do slide anterior
protected void imprimeNome() {
SuperClasse sup = (SuperClasse) this;
System.out.print(“this.nome(): ”);
this.nome();
System.out.print(“sup.nome(): ”);
sup.nome();
System.out.print(“super.nome(): ”);
super.nome();
}
}
No terminal é impresso this.nome(): SubClasse
sup.nome(): SubClasse
super.nome(): SuperClasse
LEEC@IST
Java – 35/52
Membros estáticos (1)
• Os membros estáticos duma classe, atributos ou
métodos, não podem ser redefinidos, são sempre
escondidos.
• Se uma referência é usada para aceder aos
membros estáticos, o membro a aceder é sempre
determinado pela classe de declaração da
referência.
LEEC@IST
Java – 36/52
Membros estáticos (2)
public class SuperClasse {
protected static String str = “SupCStr”;
public static void imprime() {
System.out.println(“SuperCImprime(): “+str);
}
}
public class SubClasse extends SuperClasse {
protected static String str = “SubCStr”;
public static void imprime() {
System.out.println(“SubCImprime(): “+str);
}
LEEC@IST
Java – 37/52
Membros estáticos (3)
//... Continuação do slide anterior
public static void main(String[] args) {
SubClasse sub = new SubClasse();
SuperClass sup = sub;
sup.imprime();
sub.imprime();
System.out.println(“sup.str = ”+sup.str);
System.out.println(“sub.str = ”+sub.str;
}
}
No terminal é impresso SupCImprime(): SupCStr
SubCImprime(): SubCStr
sup.str = SupCStr
sub.str = SubCStr
LEEC@IST
Java – 38/52
Conversão explícita (1)
• Um cast é usado para dizer ao compilador que uma
expressão deve ser vista como tendo o tipo
espeficicado pelo cast.
– Upcast: cast de um classe para outra acima na hierarquia
de classes (de subclasse para superclasse, não
necessariamente directa).
– Downcast: cast de uma classe para outra abaixo na
hierarquia de classes (de superclasse para subclasse, não
necessariamente directa).
• Se o objecto não pertencer a classe especificada é gerado um
excepção de tempo de execução.
• O upcast é também conhecido como cast seguro,
porque é sempre válido. No o downcast é verificado
em tempo de execução.
LEEC@IST
Java – 39/52
Conversão explícita (2)
•
•
•
No Java, um atributo ou variável local de uma superclasse pode
referenciar qualquer das suas subclasses.
subclasses
No entanto, só podem ser (directamente) chamados os atributos e
métodos definidos na superclasse.
Ou seja o objecto é tratado como se fosse da superclasse.
public class A {
void foo() {...}
...
}
public class B extends A {
void b() {...}
...
}
LEEC@IST
public class Armazem {
A var[] = new A[2];
void xpto(){
var[0] = new A();
var[0].foo();
var[1] = new B();
var[1].foo();
}
}
Java – 40/52
Conversão explícita (3)
•
Relativamente ao exemplo anterior:
– Tanto var[0] como var[1] não têm acesso (directo) ao
método foo() de B (mesmo tendo sido var[1] instanciado
como um objecto de tipo B).
– No entanto, var[1] pode aceder ao método b() através dum
downcast:((B)var[1]).b();
– Se a subclasse B redefinir o método foo(), qual o código
executado na chamada var[1].foo()?
• Executa-se sempre o método mais abaixo na hierarquia de
classes, portanto a resposta correcta seria foo() de B
(ver slide 25).
LEEC@IST
Java – 41/52
Herança e sobreposição (1)
•
Uma classe X diz-se compatível (assignment
compatible) com uma classe Y se:
Z
– X=Y, ou
– X é uma subclasse de Y (directa ou indirecta)
•
Uma classe X é mais específica que classe Y
Y
– X é uma subclasse de Y (directa ou indirecta)
X
•
A compatibilidade também pode ser aplicada a tipos primitivos,
usando-se neste caso a ordenação dada na conversão implícita
dos mesmos:
byte->short->int->long->float->double
LEEC@IST
Java – 42/52
Herança e sobreposição (2)
• Quando um método é chamado e há sobreposição de métodos,
de tal forma que o tipo dos parâmetros dos métodos sobrepostos
se encontram numa mesma hierarquia, o compilador escolhe o
método mais específico (se existir).
– A determinação do método a chamar é feita em tempo
de compilação, baseada no tipo declarado das
referências passadas aos métodos, e no valor dos
argumentos.
– Este processo determina apenas qual o método a
chamar, não qual a implementação. Em tempo de
execução, a classe de instanciação do objecto sobre o
qual o método é chamado é que vai determinar qual a
implementação do método, escolhido em tempo de
compilação, que vai ser usada.
LEEC@IST
Java – 43/52
Herança e sobreposição (3)
•
Determinação do método mais específico:
1. Determinar a classe sobre a qual procurar pelo método.
2. Determinar todos os métodos dessa classe que possam
ser aplicados:
a) Métodos com visibilidade correcta.
b) Métodos com o mesmo identificador.
c) Métodos que possam receber o número de argumentos
passados.
d) Métodos cujos tipos dos parâmetros sejam compatíveis com
os tipos declarados das referências passadas como
argumento.
LEEC@IST
Java – 44/52
Herança e sobreposição (4)
2.
(cont.)
A compatibilidade dos tipos em 2.d) é feita em 3 fases:
i.
A compatibilidade é considerada sem tentar nenhuma
conversão de embrulho (boxing conversion), e sem
considerar a possibilidade de número variável de
argumento.
ii. Se 1. falhar, a compatibilidade é considerada com a
possibilidade de conversão de embrulho (boxing
conversion).
iii. Se 2. falhar, a compatibilidade é considerada com a
possibilidade de número variável de argumentos.
LEEC@IST
Java – 45/52
Herança e sobreposição (5)
São eliminados todos os métodos em todos os argumentos
sejam superclasses dos argumentos de outro método.
todo Ou
seja aqueles em que exista um método com todos os argumentos
mais específicos que os de outro método.
Exemplo: O Método3 é eliminado porque todos seus argumento são
super classes tanto Metodo1 como de Método2.
Método2 e Método1 não são eliminados porque alguns dos seus
argumentos são superclasses do outro enquanto que outros são
subclasses. Nenhum dos métodos é definitivamente o mais
especifico que outro e um erro de compilação será gerado.
Chamada do método: foo(“123”, “abc”);
Método1: Void foo(String a, Object b);
Método2: Void foo(object a, String b);
Método3: Void foo(Object a, Object b);
LEEC@IST
Java – 46/52
Herança e sobreposição (6)
4.
Determinar o método a chamar:
a) Se apenas um método foi escolhido em 3., esse método é o
mais específico e é chamado.
b) Se foi escolhido mais de um método em 3. temos duas
hipóteses:
i. Se os métodos têm assinaturas diferentes, a chamada é
ambígua e o código que o chama é inválido.
ii. Se os métodos têm a mesma assinatura temos três
hipóteses:
–
–
–
LEEC@IST
Se todos os métodos são abstractos, é escolhido um ao
acaso.
Se apenas um método não é abstracto, é escolhido esse
método.
De qualquer outra forma a chamada é ambígua e o código
que o chama é inválido.
Java – 47/52
Herança e sobreposição (7)
Sobremesa
Bolo
BoloChocolate
void
void
void
void
Scone
As seguintes chamadas:
• xpto(sobremesaRef, sconeRef);
• xpto(boloChocRef, sobremesaRef);
• xpto(boloChocRef, sconeAmanteigadoRef);
• xpto(boloRef, sconeRef);
• xpto(sconeRef, boloRef);
resultam na chamada de que forma do método xpto?
SconeAmanteigado
xpto(Sobremesa d, Scone s) {...}
xpto(Bolo c, Sobremesa d) {...}
xpto(BoloChocolate cc, Scone s) {...}
xpto(Sobremesa... ds) {...}
LEEC@IST
//
//
//
//
1ª
2ª
3ª
4ª
forma
forma
forma
forma
Java – 48/52
Herança e sobreposição (8)
Sobremesa
•
Relativamente ao exemplo anterior:
Bolo Scone
– xpto(dessertRef, sconeRef);
resulta na chamada da 1ª forma do método xpto.
– xpto(chocolateCakeRef, dessertRef);
BoloCh Scone
resulta na chamada da 2ª forma do método xpto. ocolat Amant
eigad
– xpto(chocolateCakeRef,
e
o
butteredSconeRef);
resulta na chamada da 3ª forma do método xpto.
– xpto(cakeRef, sconeRef);
é inválida.
– xpto(sconeRef, cakeRef);
resulta na chamada da 4ª forma do método xpto.
LEEC@IST
Java – 49/52
Herança e sobreposição (9)
•
No exemplo anterior,
xpto(boloRef, sconeRef);
é uma chamada inválida, contudo:
– Com o cast (Sobremesa)boloRef a chamada
xpto((Sobremesa)boloRef, sconeRef);
resultaria na chamada da 1ª forma de xpto.
– Com o cast (Sobremesa)sconeRef a chamada
xpto(boloRef, (Sobremesa)sconeRef);
resultaria na chamada da 2ª forma de xpto.
LEEC@IST
Java – 50/52
Herança e sobreposição (10)
void
void
void
void
void
void
xpto(byte b) {...}
xpto(Short s) {...}
xpto(int i) {...}
xpto(Long i) {...}
xpto(float f) {...}
xpto(Double d) {...}
//
//
//
//
//
//
1ª
2ª
3ª
4ª
5ª
6ª
forma
forma
forma
forma
forma
forma
As seguintes chamadas:
• xpto(byteRef);
• xpto(shortRef);
• xpto(intRef);
• xpto(longRef);
• xpto(floatRef);
• xpto(doubleRef);
resultam na chamada de que forma do método xpto?
(cuidado com conversões de boxing e unboxing)
LEEC@IST
Java – 51/52
Herança e sobreposição (11)
•
Relativamente ao exemplo anterior:
– xpto(byteRef);
resulta na chamada da 1ª forma do método xpto.
– xpto(shortRef);
resulta na chamada da 3ª forma do método xpto.
– xpto(intRef);
resulta na chamada da 3ª forma do método xpto.
– xpto(longRef);
resulta na chamada da 5ª forma do método xpto.
– xpto(floatRef);
resulta na chamada da 5ª forma do método xpto.
– xpto(doubleRef);
resulta na chamada da 6ª forma do método xpto.
LEEC@IST
Java – 52/52
Download