Restrições de acesso

O exemplo da classe Ponto3D ilustra a forma básica de herança -- uma vez que uma classe tenha sido definida como derivada de outra, ela preserva da superclasse os atributos (no caso, os valores das coordenadas x e y) e seus métodos (no caso, o método distancia(Ponto2D) aplicado a um Ponto3D).

No entanto, deve ser observado que nenhum método definido para a classe Ponto3D pode ter acesso aos atributos x e y, pois esses são declarados como private da classe Ponto2D. De fato, caso tente-se definir naquela classe um método para calcular a distancia entre dois pontos no espaço, tal como:

    public double distancia(Ponto3D p) {
	double distX = p.x - x;
	double distY = p.y - y;
	double distZ = p.z - z;
	return(Math.sqrt(distX*distX + distY*distY + distZ*distZ));
    }
os seguintes erros seriam detectados pelo compilador Java:
Ponto3Derr.java:35: No variable x defined in class Ponto3D.
	double distX = p.x - x;
	                ^
Ponto3Derr.java:35: Undefined variable: x
	double distX = p.x - x;
	                     ^
Ponto3Derr.java:36: No variable y defined in class Ponto3D.
	double distY = p.y - y;
	                ^
Ponto3Derr.java:36: Undefined variable: y
	double distY = p.y - y;
	                     ^
ou seja, mesmo embora a classe Ponto3D tenha os atributos x e y, métodos dessa classe não podem manipulá-los diretamente.

Uma alternativa para permitir que classes derivadas possam manipular atributos da superclasse é declarar tais atributos como protected ao invés de private. Assim, objetos de classes derivadas têm acesso tanto de leitura como de escrita para esses atributos:

  public class Ponto2D {
    protected int x;
    protected int y;
    ...
  }
    

Caso deseje-se dar acesso apenas de leitura a esses atributos, uma outra alternativa é usar um método acessor para cada atributo, ou seja, um método que simplesmente retorna o valor do atributo. Nesse exemplo, a classe Ponto2D definiria dois métodos,

    public int getX() {
	return x;
    }

    public int getY() {
	return y;
    }
que permitem que qualquer objeto de qualquer classe consiga ler os valores de x e y -- mas não alterá-los. Assim, a classe Ponto3D poderia definir o método para a distância no espaço como
    public double distancia(Ponto3D p) {
	double distX = p.getX() - this.getX();
	double distY = p.getY() - this.getY();
	double distZ = p.z - z;
	return(Math.sqrt(distX*distX + distY*distY + distZ*distZ));
    }
que compilaria e executaria sem erros.

Pode-se também permitir acesso de apenas leitura para as classes derivadas (ou do mesmo pacote) mas não para as demais classes -- nesse caso, os métodos acessores seriam declarados como protected, como em

    protected int getX() {
	return x;
    }

    protected int getY() {
	return y;
    }

O método distancia(Ponto3D) não precisaria sofrer nenhuma modificação, mas outras classes não-derivadas de Ponto2D não teriam mais como invocar esses métodos acessores.


© Ivan Luiz Marques Ricarte
DCA/FEEC/UNICAMP

Last modified: Thu Feb 27 15:27:08 BRT 2003