Como não quebrar o encapsulamento na herança?

Olá, pessoal.

Tem algum modificador de escopo em que eu declare um atributo ou método na superclasse e ele seja somente visível nas subclasses? Se eu declarar com o escopo default ou protected, não somente a classe e subclasses terão acesso ao membro, mas todas as classes do pacote! E no protected ainda tem o agravante de uma classe fora do pacote ter acesso ao membro protected desde que a classe que declara o membro protected seja superclasse da classe fora do pacote.

Alguém sabe se no Tiger saiu algum novo modificador de espopo para contornar essa situação?

Abraços,

Reinaldo.

Sua explicação foi bem confusa… mas o que você quer nao é um membro privado não? as subclasses vão herdar eles e poderão acessa-los…

public class Classe{
   private int membro1;
}
public class SubClasse extends Classe{
   
    public static void main(String[] args){
      SubClasse sub = new SubClasse();
      sub.membro1 = 10;
   }
}

e não existe nem novo modificador não…

Acredito q para o seu caso protected irá servir. Preste atenção no q vc escreveu e vai ver q entrou em contradição:

[quote=“reolca”]Olá, pessoal.

Tem algum modificador de escopo em que eu declare um atributo ou método na superclasse e ele seja somente visível nas subclasses?
[/quote]

Se eu entendi vc quer um modificador para q as subclasses possam ver a variavel (ou método) certo!? Dai vc manda essa, contradizendo o q quer:

Ta certo q a classe vai estar fora do pacote, mas eh filha da classe q tem a variavel (ou método) protected, e nao era isso mesmo q vc queria!?!?

Cara, como o pessoal e nem eu acabamos entendendo muito bem a sua duvida vou postar a definição de cada um dos modificadores de acesso , assim você mesmo pode definir qual o melhor a ser usado!

Private

O modificador de acesso private e o mais restritivo de todos, variáveis, métodos e construtores com esse modificador são visíveis somente dentro da definição da própria classe, acessando-o diretamente ou através de uma instância da mesma classe.

Friendly ou Default

O acesso friendly em Java decorre da não especificação de nenhum dos três modificadores de acesso (private, protected, public), na verdade não há nenhuma palavra chave que defina que um determinado elemento terá acesso friendly. O acesso friendly pode ser aplicado a classes, métodos, variáveis e construtores. Outros nomes também usados para designar esse tipo de acesso são: “package” e “default”.

O efeito de aplicarmos o acesso friendly a um elemento (ou seja, não aplicar nenhum dos três modificadores) e que elementos com esse tipo de acesso podem somente ser acessados por classes do mesmo pacote.

Protected

O modificador de acesso protected define que variáveis, métodos e construtores com esse modificador podem somente ser acessados por classes no mesmo pacote ou subclasses da classe onde o elemento foi definido, é importante notar que para os elementos serem acessados na subclasse não é preciso estar no mesmo pacote da classe pai. O modificador protected pode ser aplicado somente em variáveis, métodos e construtores, o seu uso em classes não é permitido.

Public

O mais abrangente de todos os tipos de acesso, o modificador public declara que elementos com esse modificador são acessíveis de qualquer classe Java. Este modificador é aplicável a variáveis, métodos, construtores e classes.

Abraços
Falou! :lol:

Pessoal, antes de mais nada gostaria de agradecer a atenção de todos.

Perdoem-me pela minha última mensagem, porque ela realmente ficou confusa. Para explicar melhor, deixem-me colocar a estrutura de duas classes, omitindo o que não é de interesse para o problema:

package lib;

public class ContaCorrente {

private double saldo;

public double getSaldo() { return this.saldo; }

// *** O problema está em deixar um escopo para setSaldo que somente
// *** esta classe e a sua subclasse, ContaCorrenteEspecial, possam
// *** acessar, e não todas as classes do pacote.
public void setSaldo(double $saldo) { this.saldo = $saldo; }

public boolean saque(double $valor) {

  if (this.saldo > $valor) {

     this.saldo = this.saldo - $valor;
     return true;

  }
  else

     return false;

}

}


package lib;

public class ContaCorrenteEspecial extends ContaCorrente {

private double limite;

public boolean saque(double $valor) {

  double saldoAntesDoSaque = this.getSaldo();

  if ((saldoAntesDoSaque + this.limite) > $valor) {

     double saldoAtualizado = saldoAntesDoSaque - $valor;
     this.setSaldo(saldoAtualizado);
     return true;

  }
  else

     return false;      

}
}

Como os colegas podem ver, eu declarei o método setSaldo na superclasse como público, o que na minha opnião quebra o encapsulamento, afinal qual a diferença entre declarar como público um método que muda o valor de um atributo diretamente ou declarar o próprio atributo como público?

Mudar o método setSaldo para o escopo “default” ou protected daria a todas as classes que fazem parte do pacote lib o direito de acessarem setSaldo diretamente, através de um objeto do tipo ContaCorrente ou ContaCorrenteEspecial, o que quebra o encapsulamento da classe pelo menos dentro do pacote.

O que eu gostaria de fazer é que setSaldo pudesse ser declarado de uma forma que ele não pudesse ser chamado diretamente por nenhum objeto da classe ContaCorrente ou ContaCorrenteEspecial (o que quero dizer com diretamente é utilizar, por exemplo, o objeto x da classe ContaCorrente para chamar setSaldo, ex: x.setSaldo(10.0)), mas somente indiretamente, ou seja, que setSaldo só fosse visível para as implementações de outros métodos das duas classes (o que quero dizer com isso é que somente dentro de um método da classe ContaCorrente ou ContaCorrenteEspecial é que eu poderia chamar setSaldo).

Se eu declarar setSaldo como private em ContaCorrente, eu fico preso a utilizá-lo somente na superclasse. Se declará-lo como protected ou “defaut”, eu o acesso na subclasse, mas em compensação eu também consigo acessá-lo de qualquer outro método de qualquer outra classe dentro desse pacote, desde que essa outra classe crie um objeto do tipo ContaCorrente ou ContaCorrenteEspecial. Isso, na minha opnião, quebra o encapsulamento da classe dentro do pacote em que foi declarada.

Se eu não me engano, em C++ quando você declara um item como protected, só é possível acessá-lo dentro das implementações da classe que o declara e dentro das implementações das suas subclasses. Isso é o que eu realmente queria? Isso é possível em Java?

Atenciosamente,

Reinaldo.

private float peso; public void setPeso(float x){ if(x<0){ System.out.print("peso não pode ser setado"); } else{ peso = x; } }
Agora imagine você podendo fazer minhaReferencia.peso= -100.

Acabei me esquecendo de falar para o Jair Elton que infelizmente a solução dele não funciona, porque declarar um mebro privado em uma classe permite o acesso deste somente nessa classe e não nas subclasses.

Mas muito obrigado pela atenção assim mesmo, Jair Elton. Se você puder, leia novamente o problema, pois dessa vez expliquei-o melhor.

Um abração e muitíssimo obrigado novamente. Pessoas como você e os outros colegas que respoderam é que fazem essa comunidade extremamente atuante.

Abraços.

private float peso; public void setPeso(float x){ if(x<0){ System.out.print("peso não pode ser setado"); } else{ peso = x; } }
Agora imagine você podendo fazer minhaReferencia.peso= -100, pra isso existe serve o encapsulamento, pra evitar esses erros acessando as variáveis e objetos diretamente.[/quote]

Realmente, essa é uma boa razão, sem dúvida! Mas eu ainda acho que o encapsulamento no caso em que eu descrevi ainda é quebrado.

Valeu pela dica!

Vamos la (2ª tentativa :smiley: )

O atributo saldo vc declara como private. (pode até ser protected, mas vamos deixar como private mesmo.)

Agora vc cria o método setSaldo como protected, e sempre q vc precisar alterar o valor de saldo, vc usa setSaldo, mas isso só ira funcionar se vc chamar da SuperClasse (onde vc definiu o método e o atributo) ou na classe herdada dessa super classe. Qq outra classe de pacote diferente ou do mesmo pacote não poderá utilizar o metodo, muito menos o atributo.

Acho q era isso q vc queria, certo?

[quote=“darkseid”]Vamos la (2ª tentativa :smiley: )

O atributo saldo vc declara como private. (pode até ser protected, mas vamos deixar como private mesmo.)

Agora vc cria o método setSaldo como protected, e sempre q vc precisar alterar o valor de saldo, vc usa setSaldo, mas isso só ira funcionar se vc chamar da SuperClasse (onde vc definiu o método e o atributo) ou na classe herdada dessa super classe. Qq outra classe de pacote diferente ou do mesmo pacote não poderá utilizar o metodo, muito menos o atributo.

Acho q era isso q vc queria, certo?[/quote]

Hehehe. Valeu pela resposta, Darkside.

Eu entendi o que você quis dizer desde a primeira vez. Realmente, o método saque só poderá ser chamado por um objeto da classe superclasse ou subclasse.

Para ilustrar o problema que eu quero resolver, vamos imaginar hipoteticamente que após eu ter criado as classes ContaCorrente e ContaCorrenteEspecial (incluindo setSaldo como protected, do jeito que você falou) , um outro programador cria mais dez classes nesse pacote lib. Aí, em três métodos de cada classe, ele cria um objeto de ContaCorrenteEspecial e chama o método setSaldo, de acordo como a seguir:

ContaCorrenteEspecial c = new ContaCorrente(); c.setSaldo(10.0);

Percebe que, se um caixa do banco perceber que tem um erro depois no saldo de um cliente, o programador vai ter que olhar os 3 métodos dessas 10 novas classes para ver onde ele possívelmente errou no código? O encapsulamento para mim é justamente para acabar com esse tipo de erro. Se setSaldo pudesse ser chamado SOMENTE dentro dos próprios métodos das classes ContaCorrente e ContaCorrenteEspecial, achar o erro seria muito mais fácil. Mas, por ser protected, um monte de outras classes puderam fazer referência direta a mudança de saldo através de setSaldo. Aí o programador vai ter que se virar e olhar todas essas 10 classes e mais a classes ContaCorrente e ContaCorrenteEspecial. Por isso que eu disse que declarar como protected um método set pode possívelmente quebrar o encapsulamento.

Um abração e valeu pela resposta.

OO eh muito bom, ajuda a diminuir muito os erros, mas nada pode evitar erros qndo o programador eh, digamos, ou estúpido ou mal-intencionado.

Agora eu entendi + ou - o que quer, mas acho muito especifico, não vejo nenhum motivo pra isso, se criar um metodo mas nao der acesso a ele nao adianta nada… no seu caso parece que quer que o metodo só seja acessivel nas subclasses, para nao acontecer de um programador usar o metodo em outra classe, certo?! e se o programador herdar sua classe? nao dá certo tambem…

o encapsulamento é para você ter mais controle na modificação dos valores dos atributos, não para facilitar a correção de erros de programação…

acho que não existe motivo para sua preocupação…

Qualquer coisa tem email e msn aí, é só falar…