Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Acces Modiffiers

Holaa comunidad, me estoy preparando desde casita para el SE 8
y cada vez que hago tests de pruebas tengo el mismo problema, los acces modifiers..Si, me se los rangos de visibilidad de cada uno, pero depende desde como se llame el objeto ya me lia bastante..Hice un ejemplo sencillo para ver si me podriais ayudar, estaria bastante agradecido:

http://i.imgur.com/OG7NwzG.jpg

(Con los public no hay problema, los private igual)

En el caso del primer objeto "a", no entiendo porque no se puede llamar al metodo a.protegido(), si supuestamente el modificador de acceso "protected" permite la visibilidad al ser B la subclase de A.

En el segudno caso mas de lo mismo, al ser un objeto A apuntando a B, con mas razon deberia dejar ejecutar el metodo ab.protegido();

Y el ultimo objeto B ya flipo un poco... espero no haber perdido el norte.

Por otro lado, me gustaria recibir algun tipo de recomendacion de como interpretais esos accesos y llamadas, ya que yo le di muchas vueltas y es probable que este muy confuso.

Y despues de haberos leido todo esto, os doy muchas gracias, ya que me estariais ayudando muchisimo.

septiembre 16, 2015 | Unregistered CommenterAlbert

El método protegido() de la clase A solo es visible dentro de objetos de la clase A, de objetos de clases del mismo paquete que A o dentro de objetos de subclases de A (esto último por herencia como método de la subclase).

Tú no lo estás invocando desde dentro de la clase A, ni de un objeto cuya clase es del mismo paquete que A, ni desde dentro de un objeto de una subclase de A invocando su propio método protegido().

Imagino que lo que te descuadra es el tercer caso. Entiende que protected, public, private y el acceso por defecto sirven para delimitar la visibilidad del miembro.

Si declaras un método como private, seguro que entiendes que no puedes hacer esto (uso las variables y clases de tu ejemplo, y entiende que estas líneas se encuentran en un método de instancia de la clase B):


// No funciona esto
a.privado();

// Pero tampoco esto
this.privado();

// Ni esto
b.privado();

Si el segundo caso no te lo esperabas, es porque el método privado es..., bueno, privado y no se hereda.

Si declaras un método con acceso por defecto, pasa esto:


// No funciona esto
a.defecto();

// Esto solo si B está en el mismo paquete que A
this.defecto();

// Y esto igual
b.defecto();

El sentido en estos casos es que las clases de un mismo paquete están relacionadas con una misma funcionalidad y probablemente necesiten acceso con ciertas confianzas entre ellas ("trabajan juntas"). Sin embargo, cualquiera puede extender nuestras clases (si no las hemos marcado como final), y por el polimorfismo esas subclases se pueden hacer pasar por nuestras clases. Al extender nuestras clases, podrían cambiar el sentido de lo que hacen por algo "maligno", o simplemente "torpe" y afectar nuestra funcionalidad. Por ello, no nos fiamos de las posibles subclases más de lo necesario, y no le enseñamos los métodos con acceso por defecto.

Si lo declaras protegido, pasa esto:


// Esto solo funciona si B está en el mismo paquete que A
a.protegido();

// Esto sí funciona
this.protegido();

// Y esto también
b.protegido();

En este caso, no nos importa que alguna subclase use esos métodos protegidos.

Un ejemplo tonto de por qué puedes querer un método público, con acceso por defecto y con acceso protegido. Imagina un método público llamado "incrementar()" que incrementa una propiedad del objeto que se usa como contador en 1, y lo hace llamando a un método con acceso por defecto llamado "sumar(int cuantoMas)". A otras clases del paquete les puede resultar útil poder incrementar el contador de golpe en 4, por ejemplo, y por eso lo declaras así.

Pero si no te fías de lo que hagan otros extendiendo tu clase, quizá no quieras que esas subclases puedan incrementar el contador más que de 1 en 1, de modo que no podrán ver el método sumar(int cuantoMas) y tendrán que usar incrementar(). Si, por el contrario, no te importa que también incrementen el contador en saltos mayores, declaras ese método protected, y a pesar de ello te aseguras de que los consumidores de tu clase (o de las posibles subclases) seguirán pidiendo incrementar el contador solo de 1 en 1, porque seguirán sin ver sumar(int cuandoMas).

¿Lo ves ahora más claro?

Ten en cuenta también que tu ejemplo usaba un método estático o de clase, no de instancia. Mis ejemplos de arriba asumen un método de instancia, para poder invocar "this".

septiembre 16, 2015 | Registered Commenterrickiees

O sea, si tengo dos clases diferentes en distintos paquetes, por mas que una herede de la otra, esta no podra ejecutar los metodos protected del padre por el hecho de estar en otro paquete?
Y que de estar en el mismo paquete lo haria?

septiembre 17, 2015 | Unregistered CommenterAlbert

No, tu ejemplo no compila xq estas intentando llamar al metodo 'protegido' de la clase 'A' fuera de 'A'.

(https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2)

septiembre 21, 2015 | Unregistered Commentermnogales