Por favor, agora eu fiquei confuso e preciso entender como isso acontece…
Considere os seguintes códigos ( definitivamente não serve pra nada, mas… ):
RetornaNumero.java:
[code]public class RetornaNumero {
public int i;
public RetornaNumero() {
i = 10;
}
}[/code]
RetornaNumeroNovo.java:
[code]public class RetornaNumeroNovo {
public void printNumero() {
System.out.println("O numero e " + i );
}
}[/code]
Teste.java:
[code]public class Teste {
public static void main ( String args[] ) {
RetornaNumeroNovo r = new RetornaNumeroNovo();
r.printNumero();
}
}[/code]
Até aí, tudo bem. Compilo os 3 arquivos fonte e que maravilha!!! Ele imprime 10 na tela!!!
Mas acontece que se eu alterar a declaração da variável i na classe RetornaNumero para private, recompilo RetornaNumero.java e executo o Teste.class, para meu espanto, o programa “ainda” imprimiu 10 na tela!!! :shock:
Na verdade a linha System.out.println("O numero e " + i ); quebra as regras de escopo… :roll:
Eu sou obrigado a recompilar todas as classes descendentes quando eu mudo uma superclasse? Não deveria ser automático, já que eu utilizo arquivos .class separados? :?:
Como assim, imprime 10 da tela? RetornaNumeroNovo.java da erro da hora de compilar, pois 'i" nao existe. Ao menos que voce tenha extendido a classe RetornaNumero e esquecido de colocar no exemplo… mas caso contrario, o exemplo ai nem ao menos compila…
Teoricamente sim, mas como o compilador poderia advinhar que existe essa classe RetornaNumeroNovo que estende a RetornaNumero? No caso elas ainda estão até perto, no mesmo pacote e tal, mas poderia acontecer de ela estar em um lugar totalmente diferente. Não dá para o seu compilador sair procurando classes assim. O que ele faz é o contrário. Se você compila uma classe, ele verifica a que classes esse arquivo faz referência, e verifica se algum deles mudou. Mas no caso, RetornaNumero não está mencioando a existência de nenhuma outra classe.
Porém, na minha opinião pessoal uma RuntimeException cairia bem neste caso…
Deve ter algo errado. Pelo código que ele passou RetornaNumeroNovo não deveria compilar. Deveria dar algo do tipo Undeclared Indentifier i ou algo semelhante.
Pessoal, realmente foi um erro ao digitar no forum , a declaração correta - e que usei no teste - é a seguinte:
public class RetornaNumeroNovo extends RetornaNumero
O resto do que foi dito é válido… desculpem pela falha…
Porque RetornaNumeroNovo não retorna um erro, já que i agora é private? Como posso evitar isso, sem ter que compilar todas as subclasses?
Tudo bem Bani, o problema não é com o compilador - é ao rodar o aplicativo. Na verdade, ao rodá-lo, RetornaNumeroNovo não irá checar as implementações de RetornaNumero? Ou isso é feito em tempo de compilação? Não estou compreendendo direito como funciona o processo e acho complicado ter que compilar todas as subclasses - se eu esquecer uma… tô ferrado…
Não quebra as regras de escopo…
Se você extende à classe RetornaNumero então “é como se fosse” o mesmo código… o que é private na classe pai é visto na classe filho…
Agora não entendi o que você teve que recompilar e o que você quer evitar…
Vc está enganado… o que é private na superclasse não é visto na subclasse… para isso teria que ser protected, ou public…
A questão é que o Java só reconheceu a mudança - de public para private - quando eu tentei compilar novamente o RetornaNumeroNovo… aí sim, ele me retornou um erro. O problema é saber porque ele não reconheceu isso quando, simplesmente, eu compilei RetornaNumero.
Parece que nao tem mto o que fazer nao… vc vai precisar recompilar tudo.
Se vc fizer no braco, pode realmente acontecer de vc esquecer de recopmilar algum .java. .nesse caso eh que uma IDE ajuda mto, pois na pior das hipoteses eh so dar um Rebuild Project … o Eclipse, por exemplo, ja verifica para vc as dependencias.
:shock:
É aconteceu mesmo. Dei um javac *.java
Blz. Depois alterei a RetornaNumero (coloquei i como private) e recompilei.
Quando rodei Teste imprimiu “O numero e 10”.
Editei novamente o RetornaNumero. Coloquei no construtor i = 500;
Recompilei RetornaNumero e rodei teste. Imprimiu “O numero e 500” :shock: :shock: :shock:
Pois é, você tem que que recompilar RetornaNumeroNovo também. É algum furo ou estamos fazendo algo de errado???
Agora Rafael, imagine que você modifica essa classe e envia para o cliente, que possui sua própria implementação. Os seus dados que agora são privados continuarão a ser acessados pelo cliente se ele não recompilar suas classes. Você não tem controle sobre as classes implementadas pelo cliente. Por isso que é mandatório. Seus atributos devem ser private e defina getters e setters publicos para eles.
Pois é Elvis, acho que é realmente um “furo” como você disse. Na verdade, ele não reconhece a mudança de escopo automaticamente, sem a recompilação das subclasses…
O que será que a Sun tem a dizer sobre este “efeito” interessante??? :roll:
Tive a pensar sobre isto e resolvi dar a minha opinião. Não acho que isto seja alguma espécie de “furo” ou “bug”. Quando a class Teste é compilada o modificador de acesso à variavel i é publico logo não podia dar problemas, só mais tarde é q o modificador de acesso é alterado para privado e não há maneira das outras classes saberam isso sem serem compiladas (É algo que não deve ser verificado em runtime). Por isso é que muitos IDEs têm a opção de “Compilar Projecto”, usada neste caso iria avisar o programor do sucessido, protegendo a class.