[RESOLVIDO]Acesso a método abstract como se fosse static

Olá!!

Eu estou com uma dúvida com relação a um acesso do código abaixo.

abstract class Midia {
protected String titulo;
public String getTitulo(){return titulo;}
public void setTitulo(String v){titulo=v;}
public abstract Midia clone();
}
class Video extends Midia{
private String produtora;
private String diretor;
public String getProdutora(){return produtora;}
public void setProdutora(String v){produtora=v;}
public String getDiretor(){return diretor;}
public void setDiretor(String v){diretor=v;}
public Midia clone() {
Video v = new Video();
v.setTitulo(titulo);
v.setProdutora(produtora);
v.setDiretor(diretor);
return v;
}
}
class Jogo extends Midia{
private String fabricante;
private int console;
public String getFabricante(){return fabricante;}
public void setFabricante(String v){fabricante=v;}
public int getConsole(){return console;}
public void setConsole(int v){console=v;}
public Midia clone() {
Jogo j = new Jogo();
j.setTitulo(titulo);
j.setFabricante(fabricante);
j.setConsole(console);
return j;
}
}
class Musical extends Midia{
private String autor;
private String produtora;
public String getAutor(){return autor;}
public void setAutor(String v){autor=v;}
public String getProdutora(){return produtora;}
public void setProdutora(String v){produtora=v;}
public Midia clone() {
Musical m = new Musical();
m.setTitulo(titulo);
m.setAutor(autor);
m.setProdutora(produtora);
return m;
}
}
class Conserto {
private Midia midia;
public Midia getMidia(){return midia;}
public void setMidia(Midia v){midia=v.clone();}
}

Esse é um exemplo simples do uso do padrão de projeto “Protótipo”.
A questão está na linha:

public void setMidia(Midia v){midia=v.clone();}

A classe Concerto tem uma referência para a classe Midia.
Em setMidia, é passado um parâmetro do tipo Midia.
O método clone() é abstrato, e não estático (static). Assim, não daria problema no código abaixo?

midia = v.clone()

Para mim, deu NullPointerException.

NullPointerException é um erro fácil de resolver:

  1. Olhe na StackTrace em que linha o erro ocorreu;
  2. Coloque um breakpoint nessa linha;
  3. Veja qual variável você está acessando está nula.

Por exemplo, nesse caso, o objeto v pode estar nulo.

[quote=ViniGodoy]NullPointerException é um erro fácil de resolver:

  1. Olhe na StackTrace em que linha o erro ocorreu;
  2. Coloque um breakpoint nessa linha;
  3. Veja qual variável você está acessando está nula.

Por exemplo, nesse caso, o objeto v pode estar nulo.[/quote]

Eu não estou preocupado com o NullPointerException, mas sim com o acesso ao método abstrato.

media = v.clone()

O método clone() é abstrato, e não estático (static). Acesso direto (sem instância) não é somente para métodos estáticos?
Outra coisa: nesse meu caso, não estou acessando a definição do método abstrato em “Midia” ?
Deveria ser permitido eu acessar o método abstrato implementado, e não a sua definição!

Alguém a me explicar o que está acontecendo?

Opa,

todas as classes que estendem Midia são Midias, concorda? Isso faz com que você não precise ter um método para cada tipo de mídia, mas sim um único método que é válido para o Video, Jogo e etc.

Quando você for chamar o setMidia, vai passar uma instância de Video, ou Jogo ou whatever que estende Midia.

O v.clone() sempre será chamado sobre um tipo concreto de mídia.

Midia m = new Video(); //A mídia é um vídeo Midia clone = m.clone(); //Chama o método clone() de vídeo.

Só um detalhe, é uma boa prática retornar o tipo da própria classe quando sobrescrever o clone:

[code]class Musical extends Midia{
private String autor;
private String produtora;
public String getAutor(){return autor;}
public void setAutor(String v){autor=v;}
public String getProdutora(){return produtora;}
public void setProdutora(String v){produtora=v;}

@Override
public Musical clone() {  
    Musical m = new Musical();  
    m.setTitulo(titulo);  
    m.setAutor(autor);  
    m.setProdutora(produtora);  
    return m;  
}  

} [/code]

[quote=ViniGodoy]O v.clone() sempre será chamado sobre um tipo concreto de mídia.

Midia m = new Video(); //A mídia é um vídeo Midia clone = m.clone(); //Chama o método clone() de vídeo.

Só um detalhe, é uma boa prática retornar o tipo da própria classe quando sobrescrever o clone:

[code]class Musical extends Midia{
private String autor;
private String produtora;
public String getAutor(){return autor;}
public void setAutor(String v){autor=v;}
public String getProdutora(){return produtora;}
public void setProdutora(String v){produtora=v;}

@Override
public Musical clone() {  
    Musical m = new Musical();  
    m.setTitulo(titulo);  
    m.setAutor(autor);  
    m.setProdutora(produtora);  
    return m;  
}  

} [/code][/quote]

Vlw pela ajuda!