Declaraciones y control de acceso Indice



Descargar 353,95 Kb.
Página1/2
Fecha de conversión19.05.2017
Tamaño353,95 Kb.
  1   2
Capítulo 1

Declaraciones y control de acceso

Indice

1. Objetivo de Certificación 1.3 - Identificadores
1.1. Convenciones del código Java
2. Objetivo de Certificación 1.4 - JavaBeans
2.1. Estándares JavaBeans
3. Objetivo de Certificación 1.1 - Declarar clases
3.1. Declaraciones y modificadores de Clases
4. Objetivo de Certificación 1.2 - Declarar Interfaces
4.1. Declaración de una interfaz
4.2. Declarando constantes de interfaz
5. Declarar miembros de una clase
5.1. Modificadores de acceso
5.2. Miembros Public
5.3. Miembros privados
5.4. Miembros protected o default
5.5. Variables locales y Modificadores de acceso
5.6. Modificadores de no acceso en miembros
5.7. Métodos final
5.8. Métodos abstract
5.9. Métodos syncronized
5.10. Métodos Native
5.11. Métodos Strictf
5.12. Métodos con lista de argumentos variable (var-args)
5.13. Declaración de constructores
5.14. Declaraciones de Variable
5.15. Declarando primitivos y Rangos de primitivos
5.16. Declaración de Variables de Referencia
5.17. Variables de instancia
5.18. Variables locales (Automática/Pila/Método)
5.19. Declaración de Array
5.20. Variables Finales
5.21. Variables Transient
5.22. Variables Volatile
5.23. Variables y Métodos estáticos
5.24. Declarando enumerados (enum)

1. Objetivo de Certificación 1.3 - Identificadores


Desarrollar código que declare, inicialice y use tipos primitivos, enumerados y objetos como estáticos, instancias y variables locales. Además, usar identificadores legales para el nombre de las variables.

Un identificador no es más que el nombre que reciben las clases, los métodos y las variables. Los identificadores legales deben estar formados solo por caracteres UNICODE, números, '$' y '_'. Utilice las siguientes reglas para asignar los identificadores:



  • Deben empezar con letra (mayúscula o minúscula), '$' o '_'. ! No pueden empezar por un número!

  • Después del primer carácter, los identificadores pueden contener cualquier letra, número, '$' o '_'.

  • No hay límite en el número de caracteres que un identificador puede tener.

  • No pueden contener signos de puntuación.

  • No podemos usar "palabras claves" como identificador.

  • Los identificadores en Java son "case sensitive" (distingue entre mayúscula y minúscula).

Ejemplos de identificadores legales:

int _a;

int $c;


int ______2_w;

int _$;


int this_is_a_very_detailed_name_for_an_identifier;

Ejemplos de identificadores ilegales:

int :b;

int -d;


int e#;

int .f;


int 7g;

Tabla con las palabras clave de Java que no podemos utilizar como identificador.





1.1. Convenciones del código Java


  • Clases e interfaces: Las clases deben ser sustantivos. Su primer carácter debe ser mayúscula el resto puede ser mayúsculas y minusculas. Por ejemplo: MiClase

Las interfaces suelen ser adjetivos. Por ejemplo: Serializable, Runnable, ...

  • Métodos: Los nombres de métodos normalmente son verbos. Se escribe el primer carácter en minúscula y el resto minúsculas y mayúsculas intercaladas. Por ejemplo: getNombre(), calcular().

  • Variables: Para las variables es igual que para los métodos. Se recomiendan nombres cortos e identificativos.

*Constantes: Son variables "static" y "final". Se deben escribir todo en mayúsculas con el carácter '_' para separar las palabras.

2. Objetivo de Certificación 1.4 - JavaBeans




Desarrollar código que declare métodos estáticos y no estáticos y usar nombres para los métodos que se ajusten al estándar de nombres de JavaBeans. Desarrollar código que declare y use una lista de argumentos variable.

2.1. Estándares JavaBeans

La especificación de JavaBeans intenta ayudar a los desarrolladores Java a crear componentes Java que pueden ser usados por otros desarrolladores de Java con una herramienta IDE como NetBeans o Eclipse. La especificación de JavaBeans garantiza que los IDE puedan reconocer y utilizar los componentes construidos por diferentes desarrolladores.


La API de JavaBeans es grande, para el examen solo habrá que estudiar algunos elementos básicos.

En primer lugar, JavaBeans son clases Java que tiene propiedades. Para nuestro propósito, pensar que las propiedades son instancias de variable private. Así la única manera de acceder a dichas propiedades desde fuera de la clase es a través de métodos de la clase. Los métodos que cambian el valor de las propiedades son métodos setter y los métodos para recuperar el valor de las propiedades son getters.


Las normas de la nomenclatura de JavaBean que debemos saber para el examen son:

  • Si la propiedad no es un booleano, el prefijo del método getter debe ser get. Por ejemplo, para la propiedad size seria getSize().

  • Si la propiedad es un booleano, el prefijo del método getteres get o is. Por ejemplo: getSttoped() o isSttoped() ambos son validos.

  • El prefijo del método setter debe ser set. Por ejemplo: setSize() es válido para la propiedad size.

  • Para completar el nombre de un método getter o setter, cambiamos el primer carácter de la propiedad a mayúscula y le ponemos el prefijo get, set o is respectivamente.

  • Los métodos setter no devuelven nada (void) y tienen un argumento que representa el tipo de la propiedad. Deben ser declarados public

  • Los métodos getter no reciben argumentos y devuelven un tipo de la propiedad. Deben ser declarados public

En segundo lugar, la especificación JavaBeans soporta eventos, que permiten a componentes notificar a otros que algo ha sucedido, son muy utilizados en aplicaciones GUI (por ejemplo click del ratón). Los objetos que reciben la información de un evento ocurrido se llaman listeners (oyentes). Para el examen, es necesario que sepamos que los métodos que se utilizan para añadir o eliminar oyentes de un evento deben también seguir la norma de denominación de JavaBean, que pasamos a describir ahora:



  • Los nombres de los métodos Listener, usados para "registrar" a un oyente en un evento, deben usar el prefijo add seguido del tipo del oyente. Por ejemplo: addActionListener() es un nombre valido.

  • Los nombres de los métodos Listener, usados para "eliminar" a un oyente en un evento, deben usar el prefijo remove seguido del tipo del oyente. Por ejemplo: addActionListener() es un nombre valido.

  • El tipo del oyente que será añadido o eliminado debe ser pasado como argumento al método.

Ejemplos de métodos JavaBeans válidos:

public void setMyValue(int v)

public int getMyValue()

public boolean isMyStatus()

public void addMyListener(MyListener m)

public void removeMyListener(MyListener m)

Ejemplos de métodos JavaBeans inválidos:

void setCustomerName(String s) // must be public

public void modifyMyValue(int v) // can't use 'modify'

public void addXListener(MyListener m) // listener type mismatch


Exam Watch


3. Objetivo de Certificación 1.1 - Declarar clases




Desarrollar código que declare clases (incluyendo abstractas y todos los demás tipos de clases), interfaces y enumerados, y hacer un uso apropiado de las sentencias "package" e "import".

Cuando escribimos código en Java, escribimos clases o interfaces. Dentro de las clases, como ya sabemos, están las variables y los métodos ( y alguna otra cosa más). Como declaremos nuestras clases, métodos y variables afecta dramáticamente la conducta del código. Por ejemplo un método público puede ser accedido desde código ejecutado fuera de nuestra aplicación, mientras que uno privado no. Por este motivo, debemos estudiar la manera de declarar y modificar (o no) una clase.

Antes de adentrarnos en las declaraciones de clases, vamos a hacer un rápido repaso a las normas asociadas con la declaración de clases, y el uso de sentencias import y package en el código fuente.


  • Cada fichero código fuente debe tener una sola clase pública.

  • Los comentarios pueden aparecer en cualquier línea de código.

  • Si hay una clase pública en un fichero, el nombre del fichero debe coincidir con el nombre de la clase pública.

  • Si la clase pertenece a un paquete, la sentencia "package" debe estar en la primera línea de código, antes de cualquier sentencia "import" que haya.

  • Si hay sentencias "import", deben estar entre la sentencia "package" (si hay) y la declaración de la clase.

  • No hay manera de declarar múltiples clases en un fichero y que tengan diferentes paquetes, o usen diferentes sentencias "import".

  • Un fichero puede tener más de una clase no pública.

  • Un fichero que no tenga clase pública puede tener cualquier nombre, no debe coincidir con el nombre de ninguna de las clases que contiene.

En el Capitulo 10 - Desarrollo, veremos con más detalle las normas implicadas en la declaración y uso de sentencias package e import, y una nueva característica de Java 5, "static import".



3.1. Declaraciones y modificadores de Clases

El siguiente código es la declaración de una clase:

class myClass {}

Este código compila bien, pero se le pueden añadir modificadores antes de la declaración de la clase. Los modificadores se dividen en dos categorías:



  • Modificadores de acceso (public, protected y private):

Sirven para restringir o permitir el acceso a una clase creada. El control de acceso de Java es un poco difícil porque hay cuatro niveles de acceso pero solo tres modificadores de acceso. El cuarto nivel de acceso ( por defecto) es cuando no utilizamos ninguno de los tres modificadores de acceso. En otras palabras, que toda clase, método y variable declarada tiene un control de acceso, indiques el tipo explícitamente o no. Aunque todos los controles de acceso funcionan para la mayoría de métodos y declaraciones de variables, una clase solo puede ser declarada como publica o por defecto; los otros dos niveles de acceso no tienen sentido para una clase, como a continuación veremos.
Java es un lenguaje centrado en paquete; los desarrolladores asumieron que para una buena organización y ámbito de nombres, se debería meter todas las clases en paquetes. Ellos tenían razón, y deberíamos imaginarnos la siguiente pesadilla: Tres programadores de la misma compañía trabajan en diferentes partes de un proyecto, escriben una clase llamada utilities . Si estas tres clases no están declaradas en ningún paquete explicito, y están en el classpath, tu no tendrás ninguna forma de decirle al compilador o JVM a cuál de las tres clases están intentando hacer referencia. Sun recomienda que los desarrolladores usen nombres de dominio invertidos, junto con alguna división y/o nombres de proyecto. Por ejemplo: Si el nombre de tu dominio es geeksanonymous.com, y tú estas trabajando en el código del cliente para el programa TwelvePointOSteps, tú deberías nombrar tu paquete algo parecido a com.geeksanonymous.steps.client. De esta forma deberías cambiar el nombre de tu clase a com.geeksanonymous.steps.client.Utilities. Es posible que aún tengas conflicto de nombres en tu propia compañía, si tú no sigues con tu propio esquema de nombres, pero con esto consigues no colisionar con clases desarrolladas en otras compañías.

Acceso a clases

Cuando queremos que una clase A tenga acceso a otra clase B, la clase A debe hacer un de las siguientes tres cosas:



  • Crear una instancia de la clase B

  • Extender de la clase B

  • Acceso seguro a métodos y variables de la clase B, dependiendo del control de acceso de estos métodos o variables.

En efecto, el acceso se conoce como visibilidad. Si la clase A no puede ver a la clase B, el nivel de acceso a los métodos y variables dentro de la clase B no tiene importancia; la clase A no tiene ninguna manera de acceder a estos métodos y variables.



Acceso por defecto
Una clase con acceso por defecto no tiene modificador precediéndola en la declaración. El nivel de acceso por defecto es a nivel de paquete, es decir una clase con acceso por defecto solo es vista por las clases de su mismo paquete. Por ejemplo si la clase A y la clase B están en diferentes paquetes, y la clase A tiene un nivel de acceso por defecto, la clase B no tiene permitido crear una instancia de la clase A, o incluso declarar una variable o devolver un tipo de clase A. De hecho, la clase B tiene que fingir que la clase A no existe, o el compilador se quejara. Mira el siguiente código:

package cert;

class Beverage { }

Ahora mira este siguiente código:

package exam.stuff;

import cert.Beverage;

class Tea extends Beverage { }

Como podemos ver , la superclase (Beverage) está en un paquete diferente de la subclase (Tea). La sentencia import del fichero Tea está intentando importar la clase Beverage. El fichero Beverage compila bien, pero cuando intentamos compilar la clase Tea obtendremos algo parecido a:



Can't access class cert.Beverage. Class or interface must be
public, in same package, or an accessible member class.
import cert.Beverage;

La clase Tea no puede compilar porque su superclase, Beverage, tiene acceso por defecto y está en un paquete diferente. Como solución a este problema podemos hacer dos cosas:



  • Poner las clases en el mismo paquete

  • Poner la clase Beverage como public (lo veremos a continuación)

Cuando veamos una pregunta con lógica compleja, nos debemos asegurar de mirar primero los modificadores de acceso. De esta forma, si encontramos una violación de acceso (por ejemplo una clase del paquete A que intenta acceder a una por defecto del paquete B), sabrás que el código no compilara, así que no pierdas el tiempo en la lógica y elige la opción "fallo de compilación" y vete a la siguiente pregunta.




Acceso público "public"

Todas las clases del universo Java tienen acceso a una clase pública. No olvides, que si una clase publica que estas intentando usar se encuentra en un diferente paquete en el cual se encuentra la clase que estamos escribiendo, deberemos importar la clase pública.

En el ejemplo que vimos anteriormente, es posible que no quiera guardar la subclase en el mismo paquete que la superclase. Para hacer que el código funcione, necesitamos añadir la palabra clave public en la declaración de la superclase, como se muestra a continuación:

package cert;

public class Beverage { }

Este cambio hace visible a la clase para todas las clases en todos los paquetes. La clase puede ser ahora instanciada desde cualquier otra clase, y cualquier clase puede extender de ella, a menos que también este marcada con el modificador de no_acceso "final".




  • Modificadores de no-acceso (incluyendo strictfp, final y abstract)

Podemos cambiar la declaración de una clase usando las palabras clave "final", "abstract" o "strictfp". Estos modificadores son adicionales a cualquier control de acceso de la clase. Por ejemplo: declarar una clase como public y final. Pero no siempre podemos mezclar modificadores de no acceso. Por ejemplo podemos usar una combinación de final y strictfp, pero nunca marcar una clase como final y abstract.


Para el examen, solo necesitamos saber que "strictfp" es una palabra clave y puede ser usada para modificar una clase o un método, pero nunca una variable. Marcando una clase como "strictfp" significa que cualquier código de método de la clase será conforme a las estándar de normas IEEE 754 para puntos flotantes. Sin este modificador, los puntos flotantes usados en los métodos podrían comportarse de una forma dependiente de la plataforma. Si tú no declaras una clase como "strictfp", aún puedes conseguir un comportamiento "strictfp" método a método.

Clases Final

Cuando usamos la palabra clave "final" en la declaración de una clase, ninguna clase puede extender de la clase final, y cualquier intento de hacerlo le dará un error de compilación.


Solo se debe marcar una clase como final si necesitamos total garantía de que ninguno de los métodos de la clase será sobrescrito.
Muchas clases en las librerías Java son finales. Por ejemplo, la clase String no puede ser extendida por ninguna otra clase. Imagine que no pudiésemos garantizar como trabaja un objeto String
Un beneficio de tener clases no finales sería el siguiente: Imagine encontrar un problema en el método de una clase que está usando, pero no tiene el código fuente. De esta forma no podemos modificar el código para mejorar el método, pero si puedes extender de la clase y sobrescribir los métodos en tu nueva subclase y sustituir la subclase en todos los sitios donde aparecía la superclase.
Vamos a modificar nuestro ejemplo Beverage para marcar al método como final:

package cert;

public final class Beverage {

public void importantMethod() { }

}

Ahora, si intentamos compilar la subclase Tea



package exam.stuff;

import cert.Beverage;

class Tea extends Beverage { }

Nosotros obtendremos algo parecido a lo siguiente:



Can't subclass final classes: class
cert.Beverage class Tea extends Beverage{
1 error

En la práctica, casi nunca vamos a crear una clase final. Una clase final elimina un beneficio clave de la programación orientada a objetos (extensibilidad, que otras clases extiendan de otra). Por lo tanto, al menos que necesitemos mucha seguridad, asume que algún día otro programador necesitara extender de tu clase.




Clases Abstractas
Una clase abstracta nunca será instanciada. Su único objetivo es ser extendida (que otra clase extienda de ella). (NOTA, sin embargo, tú puedes compilar y ejecutar una clase abstracta, siempre y cuando tú no intentes instanciarla). ¿Porque hacer una clase si no podemos hacer objetos fuera de ella?. Debido a que la clase puede ser demasiado abstracta. Por ejemplo, imagina que tienes una clase Car que tiene métodos comunes con todos los vehículos. Pero tú no quieres que nadie cree un objeto abstracto Car genérico. Lo que necesitas es instanciar tipos de coche como BMWBoxster y Subaruoutback. Eche un vistazo a la siguiente clase abstracta:

abstract class Car {

private double price;

private String model;

private String year;

public abstract void goFast();

public abstract void goUpHill();

public abstract void impressNeighbors();

// Additional, important, and serious code goes here

}

Este código compilara bien. Pero si intentamos instanciar un Car in otra código, el compilador nos dará un error de compilación similar al siguiente:



AnotherClass.java:7: class Car is an abstract

class. It can't be instantiated.

Car x = new Car();

1 error



NOTA: Los métodos marcados abstractos acaban en ";" y no en llaves "{}".

Nosotros veremos los métodos abstractos con más detalle después en este objetivo, pero recordar que siempre que haya un método abstracto en una clase, esa clase debe ser marcada como abstracta. Un método abstracto spoils the whole bunch .Pero, sin embargo, podemos poner métodos no abstractos en una clase abstracta. Por ejemplo: tu necesitarías tener métodos con implementaciones que no deberían cambiar de un tipo de Car a otro, tales como "getColor()" o "setPrice". Por poner métodos abstractos en una clase abstracta, las subclases de la clase abstracta heredan métodos implementados. La buena noticia es que las subclases heredan funcionalidad, y necesitan implementar solo los métodos que definen el comportamiento específico de la subclase.


Codificando con tipos de clases abstractas permite obtener ventajas de polimorfismo y dar un mayor grado de flexibilidad y extensibilidad. Aprenderemos más sobre polimorfismo en el Polimorfismo.
No podemos marcar una clase como abstracta y final. Porque tienen significados opuestos, una clase abstracta debe ser extendida por otras clases mientras que una final no tendrá clases que extiendan de ella. Si vemos una combinación de estos modificadores, usados para la declaración de un método o clase, el código no compilara.

4. Objetivo de Certificación 1.2 - Declarar Interfaces




Desarrollar código que declare una interfaz. Desarrollar código que implemente o extienda de una o más interfaces. Desarrollar código que declare una clase abstracta. Desarrollar código que extienda de una clase abstracta.

4.1. Declaración de una interfaz

Cuando creas una interfaz, estas definiendo un contrato de lo que la clase podrá hacer, sin decir nada sobre como lo hará.


Las interfaces pueden ser implementadas por cualquier clase, desde cualquier árbol de herencia. Esto te permite tomar clases diferentes y darles una característica común. Por ejemplo, la clase Balón y la clase Neumático tienen Botar como comportamiento, pero Balón y Neumático no comparten ninguna relación de herencia (Balón extiende de Juguete y Neumático de java.lang.Object). Pero haciendo que ambas clases implementen la interfaz Botable (del verbo botar), estaremos diciendo que ambos pueden ser tratados como, "Cosas que pueden botar", que en el lenguaje Java significa "Cosas que pueden invocar los métodos botar() y setBotarFactor()". La siguiente figura muestra la relación entre interfaces y clases.

Una interfaz define métodos abstractos que toman la siguiente forma:

abstract void bounce(); // Ends with a semicolon rather than

// curly braces


Parece que son iguales una interfaz que una clase abstracta, pero no es así. Mientras una clase abstracta puede definir tanto métodos abstractos como no abstractos, una interfaz solo puede tener métodos abstractos. Otra manera de diferenciar las interfaces de las clases abstractas es que las interfaces tienen muy poca flexibilidad en como los métodos y variables definidas en la interfaz son declaradas. Las siguientes normas son estrictas:



  • Todos los métodos de una interfaz son implícitamente públicos y abstractos.

  • Todas las variables definidas en una interfaz deben ser públicas, estáticas y finales, en otras palabras, las interfaces solo pueden declarar constantes, no instancias de variables.

  • Los métodos de una interfaz no deben ser estáticos.

  • Debido a que los métodos de una interfaz sin abstractos, no pueden ser marcados como final, strictfp o nativo

  • Una interfaz puede extender de una o más interfaces.

  • Una interfaz no puede extender de cualquier cosa excepto de una interfaz.

  • Una interfaz no puede implementar otra interfaz o clase.

  • Una interfaz debe ser declarada con la palabra clave "interface".

  • Los tipos de interfaz pueden ser usados polimórficamente (ver capitulo 2 Polimorfismo para más detalle.)

A continuación mostraremos una declaración legal de una interfaz:

public abstract interface Rollable { }

Las interfaces son implícitamente abstractas, se considera redundante márcala como abstracta. Solo debemos saber que las dos siguientes declaraciones son legales:

public abstract interface Rollable { }

public interface Rollable { }


El modificador "public" es requerido si deseas que la interfaz sea pública y no tenga un nivel de acceso por defecto.


A continuación mostramos como se declaran los métodos de una interfaz.

public interface Bounceable {

public abstract void bounce();

public abstract void setBounceFactor(int bf);

}

Marcar los métodos con los modificadores public y abstract es redundante, ya que todos los métodos de una interfaz son implícitamente public y abstract. Veremos a continuación como el código siguiente es equivalente al anterior:



public interface Bounceable {

void bounce(); // No modifiers

void setBounceFactor(int bf); // No modifiers

}


Los siguientes cinco métodos declarados con una combinación de modificadores public, abstract o no modificadores son legales e idénticos.

void bounce();

public void bounce();

abstract void bounce();

public abstract void bounce();

abstract public void bounce();


Las siguientes declaraciones de métodos de una interfaz no pueden compilar:

final void bounce(); // final and abstract can never be used

// together, and abstract is implied

static void bounce(); // interfaces define instance methods

private void bounce(); // interface methods are always public

protected void bounce(); // (same as above)


4.2. Declarando constantes de interfaz

Tienes permitido poner constantes en una interfaz. Al hacerlo, garantizas que ninguna clase que implemente la interfaz tendrá acceso a la constante.


Colocando las constantes de forma correcta en una interfaz, cualquier clase que implemente la interfaz tendrá acceso directo a las constantes, como si la clase la heredara.
Tu necesitas recordar una regla clave para las constantes de interfaz. Siempre deben ser "public static final".
NOTA Puesto que las constantes de interfaz son definidas en una interfaz, no tienen que ser declaradas como public, static *o* final. Siempre son public, static *y* final. Cualquier variable definida en una interfaz debe ser (e implicitamente lo es) una constante. Mira a ver si puedes encontrar el problema con el siguiente código (asume que estan en ficheros separados):

interface Foo {

int BAR = 42;

void go();

}

 

class Zap implements Foo {



public void go() {

BAR = 27;

}

}


¡Tu no puedes cambiar el valor de una constante! Una vez que el valor haya sido asignado, el valor nunca puede ser modificado. La asignacion de la constante sucede en la propia interfaz ( donde es declarada), asi la clase que implementa la interfaz puede acceder a ella y usarla , pero como solo lectura. Asi que la asignación BAR = 27 no compilara.

5. Declarar miembros de una clase

Los métodos e instancias de variables son conocidos normalmente como miembros. Podemos modificar un miembro con ambos modificadores de acceso y no acceso, y tenemos mas modificadores a elegir y combinar, que cuando declarábamos una clase.



5.1. Modificadores de acceso

Donde una clase puede usar dos de los cuatro niveles de control de acceso (por defecto y public), los miembros pueden usarlos todos (los cuatro):



  • public

  • protected

  • private

  • default

La protección por defecto es cuando tu no indicas en la declaración del método ningún tipo de modificador de acceso. El control de acceso por defecto y protected tienen casi el mismo comportamiento, excepto una diferencia que comentaremos mas tarde.


Es crucial entender los dos diferentes tipos de acceso:

  • El primer tipo de acceso es cuando un método de una clase intenta acceder al método o a la variables de otra clase, usando el operador punto (.) para invocar una metodo o recuperar una variable. Por ejemplo:

class Zoo {

public String coolMethod() {

return "Wow baby";

}

}

class Moo {



public void useAZoo() {

Zoo z = new Zoo();

// If the preceding line compiles Moo has access

// to the Zoo class

// But... does it have access to the coolMethod()?

System.out.println("A Zoo says, " + z. coolMethod());

// The preceding line works because Moo can access the

// public method

}

}




  • El segundo tipo de acceso es cuando una clase hereda los miembros de otra clase. Para este caso debemos recordar, que si una clase hereda un miembro, la subclase tiene dicho miembro. Por ejemplo:

class Zoo {

public String coolMethod() {

return "Wow baby";

}

}

class Moo extends Zoo {



public void useMyCoolMethod() {

// Does an instance of Moo inherit the coolMethod()?



System.out.println("Moo says, " + this.coolMethod());

// The preceding line works because Moo can inherit the

// public method

// Can an instance of Moo invoke coolMethod() on an

// instance of Zoo?

Zoo z = new Zoo();



System.out.println("Zoo says, " + z.coolMethod());

// coolMethod() is public, so Moo can invoke it on a Zoo

//reference

}

}


La siguiente figura compara una clase heredando y accediendo usando una referencia al miembro de otra clase.


Muchos de los acceso de control se centran en mirar si las dos clases involucradas están en el mismo o en o diferente paquete. No olvidar, sin embargo, que si la clase A en si no puede ser accedida por la clase B, entonces no hay miembros de la clase A que puedan ser accedidos por la clase B.

Debemos saber el efecto de diferentes combinaciones de acceso de clases y miembros ( tal como una clase por defecto con una variable publica). Primero debemos mirar el nivel de acceso de la clase. Si la clase en si no es visible a otras clase, entonces ninguno de los miembros, aunque sea public, sera visible tampoco. Una vez hayamos confirmado que la clase es visible, entonces debemos mirar el nivel de acceso individual de cada miembro.

5.2. Miembros Public

Cuando un miembro es declarado public significa que todas las clases, independientemente del paquete al que pertenezca, pueden acceder al miembro (asumiendo que la clase es visible).


Mira el siguiente código:

package book;

import cert.*; //Import all classes in the cert package

class Goo {

public static void main(String[] args) {

Sludge o = new Sludge();

o.testIt();

}

}


Ahora mira las siguientes lineas:

package cert;

public class Sludge {

public void testIt() { System.out.println("sludge"); }

}


Como podemos ver, Goo y Sludge se encuentran en diferentes paquetes. Sin embargo, Goo puede invocar al método testIt() en Sludge sin problemas debido a que la clase Sludge y el método testIt() son públicos.

Desde una subclase, si un miembro de la superclase es declarado público, la subclase hereda esos miembros independientemente de si están o no en el mismo paquetes las clases.

package cert;

public class Roo {

public String doRooThings() {

//imagine the fun code that goes here

return "fun";

}

}



La clase Roo declara el miembro doRooThings() como público. Así que si nosotros creamos una subclase de Roo, cualquier código de la subclase pueda llamar a su propio método doRooThings() heredado.

package notcert;// Not the package Roo is in

import cert.Roo;

class Cloo extends Roo {

public void testCloo() {

System.out.println(doRooThings());

}

}


Mira en el código anterior como el método doRooThings() es invocado sin necesidad de tener una referencia. Recuerda, si tu ves un método invocado (o una variable accedida) sin el operador punto (.), sabrás que el método o la variable pertenecen a la clase donde estas viendo el código. También sabrás que el método o la variable están siendo implícitamente accedidos usando la referencia this. Así que en el código anterior, la llamada a doRooThings() en la clase Cloo podría haberse escrito también como this.doRooThings(). La referencia this siempre se refiere al actual objeto en ejecución, en otras palabras, el código donde tu ves la referencia this.

Ademas de ser capaz de invocar al método doRooThings() por si misma, el código de alguna otra clase puede llamar a doRooThings() con una instancia de Cloo, como en el siguiente:

class Toon {

public static void main(String[] args) {

Cloo c = new Cloo();



System.out.println(c.doRooThings()); //No problem; method//

is public

}

}

5.3. Miembros privados


Los miembros marcados como "private" no pueden ser accedidos por código desde cualquier clase distinta de la clase en la que el miembro es declarado. Vamos a hacer un pequeño cambio a la clase Roo de un ejemplo anterior:


El método doRooThings() es ahora privado, asi que ninguna otra clase puede usarlo. Si nosotros intentamos invocar al método desde cualquier otra clase, tendremos problemas al ejecutar:

package notcert;

import cert.Roo;

class UseARoo {

public void testIt() {

Roo r = new Roo(); //So far so good; class Roo is public



System.out.println(r.doRooThings());// Compiler error!

}

}


Si nosotro intentamos compilar UseARoo, nosotros obendremos un error del compilador parecido al siguiente:



cannot find symbol
symbol : method doRooThings()

Es como si el método no existiera. Un miembro privado es invisible a cualquier código fuera de los propios miembros de la clase.


Cuando un miembro es declarado privado, una subclase no puede heredarlo. Para el examen, necesitamos reconocer que una subclase no puede ver o usar el miembro privado de la superclase. Podemos sin embargo, declarar un método similar en la subclase. Pero independientemente de como se vea, no es un método sobrescrito. Es simplemente un método que resulta tener el mismo nombre que un método privado ( que tu no sabias nada de el) de la superclase. Las reglas de sobrescritura no se aplican, asi que puedes hacer con el método lo que quieras.

package cert;

public class Roo {

private String doRooThings() {

//imagine the fun code that goes here, but no other class//

will know

return "fun";

}

}


El método doRooThings()esta ahora fuera de limites para todas las subclase, incluso los que estan en el mismo paquete como la superclase:

package cert; //Cloo and Roo are in the same package

class Cloo extends Roo {// Still OK, superclass Roo is public

public void testCloo() {

System.out.println(doRooThings()); //Compiler error!

}

}


Si nosotros intentamos compilar la subclase Cloo, el compilador mostrara algo parecido a lo siguiente:



%javac Cloo.java
Cloo.java:4: Undefined method: doRooThings()
System.out.println(doRooThings());
1 error

NOTA: Aunque tengamos permitido marcar instancias de variables como publicas, en la practica es mejor marcarlas como private o protected. Si las variables necesitan ser cambiadas, o leídas , los programadores deberían usar métodos de acceso públicos para acceder a ellas. Asi que el código en cualquier otra clase tiene que llamar al get o set de la variable, en lugar de acceder a ella directamente. Los métodos de acceso toman la forma get (para booleanos is) y set, y proporcionan un lugar donde verificar y validar antes de devolver o modificar el valor.

Un método privado no puede ser sobrescrito por una subclase. Desde la subclase, como hemos visto, no podemos heredar un método privado, por lo tanto no puede sobrescribir al método. En la siguiente figura veremos los efectos de los modificadroes private y public en clases desde el mismo o diferente paquete:

5.4. Miembros protected o default

Los niveles de control de acceso protected y por defecto son casi idénticos, pero con una diferencia. Un miembro con control de acceso por defecto debe ser accedido solo si la clase que esta accediendo esta dentro del mismo paquete, sin embargo un miembro protected puede ser accedido por una subclase aunque estén en diferentes paquetes.


Mira las siguientes dos clases en diferentes ficheros:

package certification;

public class OtherClass {

void testIt() { //No modifier means method has default//

access

System.out.println("OtherClass");

}

}


package somethingElse;

import certification.OtherClass;

class AccessClass {

static public void main(String[] args) {

OtherClass o = new OtherClass();

o.testIt();

}

}


El compilador devolverá algo parecido a:

No method matching testIt() found in class
certification.OtherClass. o.testIt();

El comportamiento del control de acceso por defecto y el protected difiere solo cuando hablamos de subclases. Si la palabra protected es usada para definir un miembro, cualquier subclase de la clase declarando el miembro puede acceder a el a través de la herencia. No nos tenemos que fijar si las clases están en diferentes paquetes, el miembro protected de la superclase es visible a la subclase (aunque visible solo en un caso muy especifico como veremos mas adelante). Hay una diferencia con el comportamiento que tendría si lo declarásemos como por defecto, ya que no permite a una subclase acceder al miembro de una superclase a menos que la subclase este en el mismo paquete que la superclase.


NOTA: Cuando pienses en acceso por defecto, piensa entonces en la restricción de paquetes.
Pero cuando tu pienses en el tipo de acceso protected, piensa en las restricciones de paquetes e hijos.
Una clase con un miembro protected tiene marcado que el miembro tiene acceso a nivel de paquete para todas las clases del paquete, pero con una excepción para las subclases fuera del paquete que heredaria el método. No significa, sin embargo, no significa que la subclase fuera del paquete pueda acceder al miembro usando una referencia a una instancia de la superclase. En otras palabras, protected = herencia. Protected no significa que la subclase pueda tratar al miembro protected de la superclase como si fuera public. Así que si la subclase fuera del paquete obtiene una referencia de las superclase ( creando la instancia en cualquier lugar del código de la subclase), la subclase no puede usar el operador punto para acceder a un miembro protected de la superclase. Para una subclase un método protected significara lo mismo que si fuese por defecto ( o incluso private), cuando la subclase use una referencia a la superclase. La subclase puede ver al miembro protected solo a través de la herencia.

Detalles de proteted

Vamos a hechar un vistazo a la instancia de la variable protected de una superclase.

package certification;

public class Parent {

protected int x = 9; //protected access

}


El código anterior declara la variable x como protected. Esto hace a la variable accesible para todas las otras clases dentro del mismo paquete, y tambien heredable para cualquier subclase fuera del paquete. Ahora vamos a crear una subclase en un paquete diferent e intentaremos usar la variable x (que la subclase herdara):

package other;// Different package

import certification.Parent;

class Child extends Parent {

public void testIt() {

System.out.println("x is " + x); //No problem; Child//

inherits x

}

}


El anterior código compila bien. Vemos como la clase hijo esta accediendo a la variable protected a través de la herencia. Recordar, que cuando hablamos de que una subclase tiene acceso al miembro de una superclase, nos referimos a que la subclase hereda el miembrp, pero no accediendo al miembro a través de una referencia mediante una instancia de la superclase. A continuación, mostraremos que sucederia en el caso de acceder a una variable protected usando una referencia a la clase Parent:

package other;

import certification.Parent;

class Child extends Parent {

public void testIt() (

System.out.println("x is " + x); //No problem; Child//

inherits x

Parent p = new Parent(); //Can we access x using the//

p reference?



System.out.println("X in parent is " + p.x); //Compiler//

error!


}

}


El compilador mostraria lo siguiente:

%javac -d . other/Child.java
other/Child.java:9: x has protected access in certification.Parent
System.out.println("X in parent is " + p.x);
^
1 error

Hasta el momento tenemos establecido que un miembro protected tiene acceso a nivel de paquete o por defecto, a todas las clases excepto a las subclases. Hemos visto que las subclase fuera del paquete pueden heredar un miembro protected. Para terminar, hemos visto que las subclase fuera del paquete no pueden usar una referencia a la superclase para acceder a un miembro protected. Para una subclase fuera del paquete, el miembro protected solo puede ser accedido a través de herencia.

Aún queda algunas cosas que mirar de los miembros protected. ¿Que sudecería si una nueva clase del mismo paquete que la subclase intenta acceder a través de una referencia de dicha subclase a la variable protected x?, en otras palabras ¿cual seria el comportamiento del miembro protected una vez la subclase lo haya heredado?.
Una vez la subclase fuera del paquete hereda el miembro protected, dicho miembro (como heredado de la subclase) se convierte en private para cualquier código fuera de la subclase, con excepción de las subclases de la subclase.

Detalles del acceso por defecto

Vamos a empezar con el comportamiento del acceso por defecto de un miembro en una superclase. Nosotros modificaremos el miembro x de Parent para hacerlo por defecto.

package certification;

public class Parent {

int x = 9; //No access modifier, means default//

(package) access

}

Ahora intentaremos acceder al miembro con acceso por defecto desde la clase Child de antes:


Cuando nosotros compilamos obtenemos un error similar a este:


Child.java:4: Undefined variable: x
System.out.println("Variable x is " + x);
1 error

El compilador da el mismo error que cuando el miembro es declarado private. La subclase Child (en un paquete diferente del de la suoerclase Parent) no puede ver o usar el miembro con acceso por defecto x de la superclase. ¿Que pasaria ahora si estuviesen en el mismo paquete?

package certification;

public class Parent{

int x = 9; //default access

}


Y en la segunda clase tu tienes lo siguiente:

package certification;

class Child extends Parent{

static public void main(String[] args) {

Child sc = new Child();

sc.testIt();

}

public void testIt() {



System.out.println("Variable x is " + x);// No problem;

}

}


El código anterior compila bien, y la clase Child ejecutara y mostrara el valor de x. Recordar que un miembro con acceso por defecto es visible por una subclase solo si esta en el mismo paquete que la superclase.



5.5. Variables locales y Modificadores de acceso

Hay una variable local no se le puede aplicar modificadores de acceso, como por ejemplo se ve en el siguiente código:

class Foo {

void doStuff() {

private int x = 7;

this.doMore(x);

}

}


Tu puedes estar seguro que cualquier variable local declarada con un modificador de acceso no compilara. De hecho, solo el modificador final puede ser aplicado a una variable local. La siguiente tabala nos muestra todas las combinaciones de acceso y visibilidad:

Visibilidad

Public

Protected

Default

Private

Desde la misma clase

si

si

si

si

Desde cualquier clase en el mismo paquete

si

si

si

no

Desde una subclase en el mismo paquete

si

si

si

no

Desde una clase fuera del paquete

si

si, a través de herencia

no

no

Desde cualquier clase no subclase fuera del paquete

si

no

no

no

  1   2


La base de datos está protegida por derechos de autor ©absta.info 2016
enviar mensaje

    Página principal