Isso eu achei estranho!

Olá!!!

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!!! :smiley:

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…

Rafael

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.

Sim, claro. Estou considerando a hipótese teórica levantada. No meu computador testei com o extends.

Pessoal, realmente foi um erro ao digitar no forum :frowning: , 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… :smiley:

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…

Caro Leandro,

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.

E o impasse continua… :roll:

Sinto muito leandro: mas membros privados só são acessados dentro da classe que os declarou.

javac *.java

RetornaNumeroNovo.java:13: i has private access in br.com.facilit.RetornaNumero
    System.out.println("O numero e " + i );
                                       ^
1 error

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.

Rafael

: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.

Ufa… pelo menos eu não estava louco… :smiley:

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:

Obrigado pela ajuda de todos…

[]'s

Foi mal mesmo minha colocação…

Quanto a dúvida, postem no forum da Sun! Vê no que dá… :smiley:

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.

É o que penso :slight_smile:

Fiquem bem