Ir a contenido principal

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. Cierta información de su perfil de developerWorks será mostrada públicamente, pero usted puede editar la información en cualquier momento. Su nombre, apellido (a menos que usted elija ocultarlo) y nombre de usuario acompañarán el contenido que usted publique.

Toda la información enviada es segura.

  • Cerrar [x]

La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

Toda la información enviada es segura.

  • Cerrar [x]

Introducción a la programación Java, parte 2: Construcciones para aplicaciones del mundo real

Funciones más avanzadas del lenguaje Java

J. Steven Perry, Consultor Director, Makoto Consulting Group, Inc.
J. Steven Perry
J. Steven Perry es desarrollador de software, arquitecto y fanático general de Java que ha estado desarrollando software profesionalmente desde 1991. Sus intereses profesionales abarcan desde el funcionamiento interno de la JVM hasta el modelo UML y todo lo que está en el medio. Steve tiene una pasión por escribir y ser mentor. Es el autor de Java Management Extensions (O'Reilly), Log4j (O'Reilly) y los artículos de developerWorks de IBM "Joda-Time" y OpenID for Java Web applications". Pasa tiempo libre con sus tres hijos, anda en bicicleta y enseña yoga.

Resumen:  En la Parte 1 de este tutorial, el programador Java™ profesional J. Steven Perry presentó la sintaxis del lenguaje Java y las bibliotecas que usted necesita para escribir aplicaciones Java simples. La Parte 2, todavía orientada a desarrolladores nuevos en el desarrollo de aplicaciones Java, presenta las construcciones de programación más sofisticadas requeridas para crear complejas aplicaciones Java del mundo real. Los temas que se cubren incluyen manejo de excepciones, herencia y abstracción, expresiones regulares, genéricos, E/S Java y serialización Java.

Ver más contenido de esta serie

Fecha:  10-12-2012
Nivel:  Introductoria PDF:  A4 and Letter (927 KB | 54 páginas)Get Adobe® Reader®

Comentario:  

Clases anidadas

En esta sección, aprenda acerca de las clases anidadas y dónde y cómo usarlas.

Dónde usar las clases anidadas

Como su nombre lo sugiere, una clase anidada es una clase que se define dentro de otra clase. Aquí hay una clase anidada:

public class EnclosingClass {
. . .
 public class NestedClass {
 . . .

 }
}

Al igual que las variables y los métodos miembro, las clases Java también se pueden definir en cualquier ámbito, incluidos los public, private o protected. Las clases anidadas pueden ser útiles cuando usted quiere manejar procesos internos dentro de su clase de un modo orientado a objetos, pero esta funcionalidad está limitada a la clase en donde la necesita.

Normalmente, usted usará una clase anidada para casos en los que necesite una clase que esté asociada firmemente con la clase en que se define. Una clase anidada tiene acceso a los datos privados dentro de su clase cerrada pero esto conlleva algunos efectos secundarios que no son evidentes cuando comienza a trabajar con clases anidadas (o internas).


Ámbito en las clases anidadas

Debido a que una clase anidada tiene un ámbito, está sujeta a las reglas del ámbito. Por ejemplo, solo se puede acceder a una variable miembro por medio de una instancia de la clase (un objeto). Lo mismo sucede con una clase anidada.

Suponga que tiene la siguiente relación entre un Manager y una clase anidada llamada DirectReports, que es una colección de los Employees que presentan informes a ese Manager:

public class Manager extends Employee {
 private DirectReports directReports;
 public Manager() {
   this.directReports = new DirectReports();
 }
. . .
 private class DirectReports {
 . . .
 }
}

Al igual que cada objeto Manager representa a un ser humano único, el objeto DirectReports representa una colección de las personas reales (empleados) que presentan informes a un gestor. DirectReports diferirá de un Manager a otro. En este caso, tiene sentido que uno sólo haga referencia a la clase anidada DirectReports en el contexto de su instancia de inclusión de Manager, por lo tanto la he hecho private.

Clases anidadas públicas

Debido a que es private, solo el Manager puede crear una instancia de DirectReports. Pero suponga que usted quisiera darle a una entidad externa la habilidad para crear instancias de DirectReports. En este caso, parece que usted podría darle a la clase DirectReports un ámbito public y entonces cualquier código externo podría crear instancias de DirectReports, como se muestra en el Listado 17:


Listado 17. Creación de instancias de DirectReports: Primer intento

public class Manager extends Employee {
 public Manager() {
 }
. . .
 private class DirectReports {
 . . .
 }
}
//
public static void main(String[] args) {
 Manager.DirectReports dr = new Manager.DirectReports();// This won't work!
}

El código en el Listado 17 no funciona y probablemente se está preguntando por qué. El problema (y también su solución) está en el modo en que se define DirectReports dentro de Manager y en las reglas del ámbito.

Revisión de las reglas del ámbito

Si usted tuviera una variable miembro de Manager, esperaría que el compilador le solicitara que tuviera una referencia a un objeto Manager antes de que pudiera hacer referencia a él, ¿verdad? Bueno, lo mismo se sucede con DirectReports, por lo menos como usted lo definió en el Listado 17.

Para crear una instancia de una clase anidada pública, se usa una versión especial del operador new. En combinación con una referencia a alguna instancia de inclusión de una clase externa, new le permite crear una instancia de la clase anidada:

public class Manager extends Employee {
 public Manager() {
 }
. . .
 private class DirectReports {
 . . .
 }
}
// Meanwhile, in another method somewhere...
public static void main(String[] args) {
 Manager manager = new Manager();
 Manager.DirectReports dr = manager.new DirectReports();
}

Observe que la sintaxis exige una referencia a la instancia de inclusión, más un punto y la palabra clave new, seguida de la clase que usted quiere crear.


Clases internas estáticas

Por momentos, querrá crear una clase que esté asociada firmemente (conceptualmente) a una clase, pero donde las reglas del ámbito estén un tanto relajadas, que no requieran una referencia a una instancia de inclusión. Allí es donde las clases internas estáticas entran en juego. Un ejemplo común de esto es implementar un Comparator, que se usa para comparar dos instancias de la misma clase, normalmente con el propósito de ordenar (o clasificar) las clases:

public class Manager extends Employee {
. . .
 public static class ManagerComparator implements Comparator<Manager> {
   . . .
 }
}
// Meanwhile, in another method somewhere...
public static void main(String[] args) {
 Manager.ManagerComparator mc = new Manager.ManagerComparator();
 . . .
}

En este caso, no necesita una instancia de inclusión. Las clases internas estáticas actúan como sus homólogas clases Java regulares y realmente solo deberían usarse cuando usted necesite asociar firmemente una clase con su definición. Claramente, en el caso de una clase de programa de utilidad como ManagerComparator, crear una clase externa es innecesario y abarrota potencialmente su base de códigos. Definir dichas clases como clases internas estáticas es lo que se tiene que hacer.


Clases internas anónimas

El lenguaje Java le permite declarar clases prácticamente en cualquier lugar, incluso en el medio de un método si es necesario, e incluso sin proporcionar un nombre para la clase. Esto es básicamente un truco de compilador pero hay momentos en que las clases internas anónimas son extremadamente útiles de tener.

El Listado 18 se desarrolla sobre el ejemplo en el Listado 15 y agrega un método predeterminado para el manejo de los tipos de Employee que no son StockOptionEligible:


Listado 18. Manejo de los tipos de Employee que no son StockOptionEligible

public static void main(String[] args) {
 Employee employee = new Manager();// perfectly valid
 handleStockOptions(employee);
 employee = new Employee();// not StockOptionEligible
 handleStockOptions(employee);
}
. . .
private static void handleStockOptions(Employee e) {
 if (e instanceof StockOptionEligible) {
   calculateAndAwardStockOptions((StockOptionEligible)e);
 } else {
   calculateAndAwardStockOptions(new StockOptionEligible() {
     @Override
     public void awardStockOptions(int number, BigDecimal price) {
       log.info("Sorry, you're not StockOptionEligible!");
     }
   });
 }
}
. . .
private static void calculateAndAwardStockOptions(StockOptionEligible soe) {
 BigDecimal reallyCheapPrice = BigDecimal.valueOf(0.01);
 int numberOfOptions = 10000;
 soe.processStockOptions(numberOfOptions, reallyCheapPrice);

}

En este ejemplo, se proporciona una implementación de la interfaz StockOptionEligible al usar una clase interna anónima para instancias de Employee que no implementan esa interfaz. Las clases internas anónimas también son útiles para implementar métodos de devolución de llamada y también en el manejo de eventos.

7 de 14 | Anterior | Siguiente

Comentario



static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=tecnologia Java
ArticleID=850709
TutorialTitle=Introducción a la programación Java, parte 2: Construcciones para aplicaciones del mundo real
publish-date=12102012
author1-email=steve.perry@makotoconsulting.com
author1-email-cc=