PROGRAMACION ORIENTADA A OBJETOS: HERENCIA

domingo, 14 de febrero de 2010

9.7 Clase Object

Como hemos comentado anteriormente en este capítulo, todas las clases en Java heredan directa o indirectamente de la clase Object (java.lang paquete), por lo que sus 11 métodos son heredados por todas las demás clases. Figura 9.18 resume los métodos de objetos.



9.6 Ingenieria desoftware mediante la herencia

9.6. Ingeniería de Software con herencia

Esta sección trata de personalizar el software existente con la herencia. Cuando una nueva clase se extiende una clase existente, la nueva clase hereda los miembros no privados de la clase existente. Podemos personalizar la nueva clase para satisfacer nuestras necesidades mediante la inclusión de nuevos miembros y por razones imperiosas miembros de la superclase. Hacer esto no requiere que el programador de la subclase de cambiar el código fuente de la superclase. Java sólo requiere el acceso a la clase de la superclase. Archivo para compilar y ejecutar cualquier programa que utilice o se extiende la superclase. Esta poderosa capacidad es atractivo para los proveedores de software independientes (ISV), que pueden desarrollar las clases de propiedad para la venta o la licencia y ponerlos a disposición de los usuarios en el formato de código de bytes. Luego, los usuarios pueden obtener nuevas clases de estas clases de biblioteca con rapidez y sin tener acceso a código fuente propiedad de los ISVs.


A veces, los estudiantes tienen dificultad para apreciar el alcance de los problemas que enfrentan los diseñadores que trabajan en grandes proyectos de software a gran escala en la industria. La gente con experiencia en este tipo de proyectos decir que la reutilización del software mejora la eficacia del proceso de desarrollo de software. Programación orientada a objetos facilita la reutilización de software, lo que podría acortar el tiempo de desarrollo.

La disponibilidad de bibliotecas de clases importante y útil ofrece los máximos beneficios de la reutilización del software a través de la herencia. Los diseñadores de aplicaciones construir sus aplicaciones con estas bibliotecas, y los diseñadores de la colección son recompensados por haber incluido en sus colecciones de las aplicaciones. Las bibliotecas de Java estándar de clase que se distribuyen con J2SE 5.0 tienden a ser de uso general. Muchos especial de las bibliotecas de clases propósito existen y se están creando más.

9.5 Los constructores en las subclases

Nuestro siguiente ejemplo vuelve a la jerarquía de empleado de la Comisión, al declarar una clase CommissionEmployee4 (Figura 9.15) y una clase BasePlusCommissionEmployee5 (Figura 9.16). Cada constructor de la clase imprime un mensaje cuando se invoca, lo que nos permite observar el orden en que los constructores de la jerarquía de ejecutar.

Figura 9.15. Salidas de CommissionEmployee4 constructor de texto.


// Fig. 9.15: EmpleadoPorComision4.java
// La clase EmpleadoPorComision4 representa a un empleado por comisión.

public class EmpleadoPorComision4
{
private String primerNombre;
private String apellidoPaterno;
private String numeroSeguroSocial;
private double ventasBrutas; // ventas totales por semana
private double tarifaComision; // porcentaje de comisión

// constructor con cinco argumentos
public EmpleadoPorComision4( String nombre, String apellido, String nss,
double ventas, double tarifa )
{
// la llamada implícita al constructor de Object ocurre aquí
primerNombre = nombre;
apellidoPaterno = apellido;
numeroSeguroSocial = nss;
establecerVentasBrutas( ventas ); // valida y almacena las ventas brutas
establecerTarifaComision( tarifa ); // valida y almacena la tarifa de comisión

System.out.printf(
"\nConstructor de EmpleadoPorComision4:\n%s\n", this );
} // fin del constructor de EmpleadoPorComision4 con cinco argumentos

// establece el primer nombre
public void establecerPrimerNombre( String nombre )
{
primerNombre = nombre;
} // fin del método establecerPrimerNombre

// devuelve el primer nombre
public String obtenerPrimerNombre()
{
return primerNombre;
} // fin del método obtenerPrimerNombre

// establece el apellido paterno
public void establecerApellidoPaterno( String apellido )
{
apellidoPaterno = apellido;
} // fin del método establecerApellidoPaterno

// devuelve el apellido paterno
public String obtenerApellidoPaterno()
{
return apellidoPaterno;
} // fin del método obtenerApellidoPaterno

// establece el número de seguro social
public void establecerNumeroSeguroSocial( String nss )
{
numeroSeguroSocial = nss; // debe validar
} // fin del método establecerNumeroSeguroSocial

// devuelve el número de seguro social
public String obtenerNumeroSeguroSocial()
{
return numeroSeguroSocial;
} // fin del método obtenerNumeroSeguroSocial

// establece el monto de ventas brutas
public void establecerVentasBrutas( double ventas )
{
ventasBrutas = ( ventas < 0.0 ) ? 0.0 : ventas;
} // fin del método establecerVentasBrutas

// devuelve el monto de ventas brutas
public double obtenerVentasBrutas()
{
return ventasBrutas;
} // fin del método obtenerVentasBrutas

// establece la tarifa de comisión
public void establecerTarifaComision( double tarifa )
{
tarifaComision = ( tarifa > 0.0 && tarifa < 1.0 ) ? tarifa : 0.0;
} // fin del método establecerTarifaComision

// devuelve la tarifa de comisión
public double obtenerTarifaComision()
{
return tarifaComision;
} // fin del método obtenerTarifaComision

// calcula los ingresos
public double ingresos()
{
return obtenerTarifaComision() * obtenerVentasBrutas();
} // fin del método ingresos

// devuelve representación String del objeto EmpleadoPorComision4
public String toString()
{
return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f",
"empleado por comision", obtenerPrimerNombre(), obtenerApellidoPaterno(),
"numero de seguro social", obtenerNumeroSeguroSocial(),
"ventas brutas", obtenerVentasBrutas(),
"tarifa de comision", obtenerTarifaComision() );
} // fin del método toString
} // fin de la clase EmpleadoPorComision4



Figura 9.16. Salidas de BasePlusCommissionEmployee5 constructor de texto.

// Fig. 9.16: EmpleadoBaseMasComision5.java
// Declaración de la clase EmpleadoBaseMasComision5.

public class EmpleadoBaseMasComision5 extends EmpleadoPorComision4
{
private double salarioBase; // salario base por semana

// constructor con seis argumentos
public EmpleadoBaseMasComision5( String nombre, String apellido,
String nss, double ventas, double tarifa, double salario )
{
super( nombre, apellido, nss, ventas, tarifa );
establecerSalarioBase( salario ); // valida y almacena el salario base

System.out.printf(
"\nConstructor de EmpleadoBaseMasComision5:\n%s\n", this );
} // fin del constructor de EmpleadoBaseMasComision5 con seis argumentos

// establece el salario base
public void establecerSalarioBase( double salario )
{
salarioBase = ( salario < 0.0 ) ? 0.0 : salario;
} // fin del método establecerSalarioBase

// devuelve el salario base
public double obtenerSalarioBase()
{
return salarioBase;
} // fin del método obtenerSalarioBase

// calcula los ingresos
public double ingresos()
{
return obtenerSalarioBase() + super.ingresos();
} // fin del método ingresos

// devuelve representación String de EmpleadoBaseMasComision5
public String toString()
{
return String.format( "%s %s\n%s: %.2f", "con sueldo base",
super.toString(), "sueldo base", obtenerSalarioBase() );
} // fin del método toString
} // fin de la clase EmpleadoBaseMasComision5



Figura 9.17 se muestra el orden en que los constructores son llamados para objetos de clases que son parte de una jerarquía de herencia. Principal método comienza por crear instancias de objeto CommissionEmployee4 employee1 (líneas 89). A continuación, las líneas de 1214 una instancia de BasePlusCommissionEmployee5 objeto employee2. Esto invoca el constructor CommissionEmployee4, que imprime la salida con los valores pasados desde el constructor BasePlusCommissionEmployee5, a continuación, realiza la salida especificada en el constructor BasePlusCommissionEmployee5. Líneas de 1719 luego una instancia de BasePlusCommissionEmployee5 objeto employee3. Una vez más, la CommissionEmployee4 y constructores BasePlusCommissionEmployee5 son llamados. En cada caso, el cuerpo del constructor CommissionEmployee4 se ejecuta antes que el cuerpo del constructor BasePlusCommissionEmployee5 ejecuta. Tenga en cuenta que employee2 está construido completamente antes de la construcción de employee3 comienza.




// Fig. 9.17: PruebaConstructores.java
// Muestra el orden en el que se llaman los constructores de la superclase y la subclase.

public class PruebaConstructores
{
public static void main( String args[] )
{
EmpleadoPorComision4 empleado1 = new EmpleadoPorComision4(
"Bob", "Lewis", "333-33-3333", 5000, .04 );

System.out.println();
EmpleadoBaseMasComision5 empleado2 =
new EmpleadoBaseMasComision5(
"Lisa", "Jones", "555-55-5555", 2000, .06, 800 );

System.out.println();
EmpleadoBaseMasComision5 empleado3 =
new EmpleadoBaseMasComision5(
"Mark", "Sands", "888-88-8888", 8000, .15, 2000 );
} // fin de main
} // fin de la clase PruebaConstructores




jueves, 11 de febrero de 2010

9.4- Relación entre superclases y subclases

En esta sección, se utiliza una jerarquía de herencia que contiene los tipos de los trabajadores en aplicación de nómina de una empresa para discutir la relación entre una superclase y la subclase. En esta empresa, los empleados por Comisión (que se representan como objetos de una superclase) se les paga un porcentaje de sus ventas, mientras que los empleados por Comisión con asalariados base (que se representan como objetos de una subclase) reciben un salario base más un porcentaje de sus ventas.

Dividimos nuestro análisis de la relación entre los empleados de la Comisión y la base de los empleados asalariados de la Comisión en cinco ejemplos. El primer ejemplo se declara CommissionEmployee clase, que hereda directamente de la clase Object y declara como variables de instancia privada de un nombre, apellido, número de seguro social, tipo de comisión y en cifras brutas (es decir, en total) cantidad de ventas.

El segundo ejemplo se declara la clase Circulo, que también hereda directamente de la clase Object y declara como variables de instancia privada de un nombre, apellido, número de seguro social, tipo de comisión, importe bruto de las ventas y el sueldo base. Creamos esta última clase de escribir cada línea de código de la clase requireswe pronto verá que es mucho más eficiente para crear esta clase que hereda de la clase EmpleadoPorComision.

El tercer ejemplo se declara una clase BasePlusCommissionEmployee2 separados que extiende la clase CommissionEmployee (es decir, un BasePlusCommissionEmployee2 es un CommissionEmployee que también tiene un sueldo base) y los intentos de acceso de clases privadas CommissionEmployee de membersthis resultados en los errores de compilación, ya que la subclase no puede acceder a las variables de instancia privada de la superclase .

El cuarto ejemplo muestra que si CommissionEmployee ejemplo de las variables son declaradas como protegidas, una clase BasePlusCommissionEmployee3 que se extiende CommissionEmployee2 clase pueden acceder a esos datos directamente. Para ello, declaramos CommissionEmployee2 clase con variables de instancia protegidos. Tanto de las clases Circulo contienen funcionalidad idéntica, pero se muestra cómo el BasePlusCommissionEmployee3 clase es más fácil crear y gestionar.

Después de discutir la conveniencia de utilizar las variables de instancia protegida, vamos a crear el quinto ejemplo, que establece las variables de instancia CommissionEmployee volver a CommissionEmployee3 privado en la clase para hacer cumplir buena ingeniería de software. A continuación se muestra cómo una clase BasePlusCommissionEmployee4 separado, que se extiende CommissionEmployee3 clase, puede utilizar métodos públicos CommissionEmployee3 para manipular las variables de instancia privada CommissionEmployee3's.


9.4.1. Crear y utilizar una clase EmpleadoPorComision

Empezamos por declarar la clase CommissionEmployee (Fig. 9.4). La Línea 4 se inicia la declaración de la clase, e indica que la clase EmpleadoPorComision se extiende (es decir, se hereda de) la clase de objeto (del paquete java.lang). Los programadores de Java utilizar la herencia para crear clases de las clases existentes. De hecho, todas las clases en Java (con excepción de objetos) se extiende una clase existente. Debido a que la clase CommissionEmployee extiende la clase de objeto, la clase CommissionEmployee hereda los métodos de la clase de objeto objectclass no tiene campos. De hecho, cada clase de Java, directa o indirectamente, hereda los métodos de objetos. Si una clase no se especifica que se extiende a otra clase, la nueva clase de objetos se extiende implícitamente. Por esta razón, los programadores no se cuenta "se extiende de objetos" en su codewe hacerlo en este ejemplo, para fines de demostración.

Figura 9.4. Clase CommissionEmployee representa un empleado pagado un porcentaje de las ventas brutas.


// Fig. 9.4: EmpleadoPorComision.java
// La clase EmpleadoPorComision representa a un empleado por comisión.

public class EmpleadoPorComision extends Object
{
private String primerNombre;
private String apellidoPaterno;
private String numeroSeguroSocial;
private double ventasBrutas; // ventas semanales totales
private double tarifaComision; // porcentaje de comisión

// constructor con cinco argumentos
public EmpleadoPorComision( String nombre, String apellido, String nss,
double ventas, double tarifa )
{
// la llamada implícita al constructor del objeto ocurre aquí
primerNombre = nombre;
apellidoPaterno = apellido;
numeroSeguroSocial = nss;
establecerVentasBrutas( ventas ); // valida y almacena las ventas brutas
establecerTarifaComision( tarifa ); // valida y almacena la tarifa de comisión
} // fin del constructor de EmpleadoPorComision con cinco argumentos

// establece el primer nombre
public void establecerPrimerNombre( String nombre )
{
primerNombre = nombre;
} // fin del método establecerPrimerNombre

// devuelve el primer nombre
public String obtenerPrimerNombre()
{
return primerNombre;
} // fin del método obtenerPrimerNombre

// establece el apellido paterno
public void establecerApellidoPaterno( String apellido )
{
apellidoPaterno = apellido;
} // fin del método establecerApellidoPaterno

// devuelve el apellido paterno
public String obtenerApellidoPaterno()
{
return apellidoPaterno;
} // fin del método obtenerApellidoPaterno

// establece el número de seguro social
public void establecerNumeroSeguroSocial( String nss )
{
numeroSeguroSocial = nss; // debe validar
} // fin del método establecerNumeroSeguroSocial

// devuelve el número de seguro social
public String obtenerNumeroSeguroSocial()
{
return numeroSeguroSocial;
} // fin del método obtenerNumeroSeguroSocial

// establece el monto de ventas totales del empleado por comisión
public void establecerVentasBrutas( double ventas )
{
ventasBrutas = ( ventas < 0.0 ) ? 0.0 : ventas;
} // fin del método establecerVentasBrutas

// devuelve el monto de ventas totales del empleado por comisión
public double obtenerVentasBrutas()
{
return ventasBrutas;
} // fin del método obtenerVentasBrutas

// establece la tarifa del empleado por comisión
public void establecerTarifaComision( double tarifa )
{
tarifaComision = ( tarifa > 0.0 && tarifa < 1.0 ) ? tarifa : 0.0;
} // fin del método establecerTarifaComision

// devuelve la tarifa del empleado por comisión
public double obtenerTarifaComision()
{
return tarifaComision;
} // fin del método obtenerTarifaComision

// calcula el salario del empleado por comisión
public double ingresos()
{
return tarifaComision * ventasBrutas;
} // fin del método ingresos

// devuelve representación String del objeto EmpleadoPorComision
public String toString()
{
return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f",
"empleado por comision", primerNombre, apellidoPaterno,
"numero de seguro social", numeroSeguroSocial,
"ventas brutas", ventasBrutas,
"tarifa de comision", tarifaComision );
} // fin del método toString
} // fin de la clase EmpleadoPorComision


9,5 Figura pruebas de clase CommissionEmployee. 9 10 líneas de una instancia de un objeto Punto e invocar el constructor CommissionEmployee (líneas 1322 de la figura. 9,4) para iniciar con "Sue", como el nombre, "Jones", el apellido, "222-22-2222", como el número de seguridad social , 10000 como el importe bruto de las ventas y .06 como el tipo de comisión. Líneas de 1524 el uso CommissionEmployee de obtener métodos para recuperar el objeto de ejemplo, valores de las variables para la salida. Líneas de 2627 invocar los métodos del objeto setGrossSales y setCommissionRate para cambiar los valores de las variables de instancia y ventasTotales commissionRate. Líneas de 2930 la producción de la representación de cadena de la CommissionEmployee actualizado. Tenga en cuenta que cuando un objeto es de salida mediante el especificador de formato% s, el método toString del objeto que se invoca implícitamente a obtener una representación de cadena del objeto.


// Fig. 9.5: PruebaEmpleadoPorComision.java
// Prueba de la clase EmpleadoPorComision.

public class PruebaEmpleadoPorComision
{
public static void main( String args[] )
{
// crea instancia de objeto EmpleadoPorComision
EmpleadoPorComision empleado = new EmpleadoPorComision(
"Sue", "Jones", "222-22-2222", 10000, .06 );

// obtiene datos del empleado por comisión
System.out.println(
"Informacion del empleado obtenida por los metodos establecer: \n" );
System.out.printf( "%s %s\n", "El primer nombre es",
empleado.obtenerPrimerNombre() );
System.out.printf( "%s %s\n", "El apellido paterno es",
empleado.obtenerApellidoPaterno() );
System.out.printf( "%s %s\n", "El numero de seguro social es",
empleado.obtenerNumeroSeguroSocial() );
System.out.printf( "%s %.2f\n", "Las ventas brutas son",
empleado.obtenerVentasBrutas() );
System.out.printf( "%s %.2f\n", "La tarifa de comision es",
empleado.obtenerTarifaComision() );

empleado.establecerVentasBrutas( 500 ); // establece las ventas brutas
empleado.establecerTarifaComision( .1 ); // establece la tarifa de comisión

System.out.printf( "\n%s:\n\n%s\n",
"Informacion actualizada del empleado, obtenida mediante toString", empleado );
} // fin de main
} // fin de la clase PruebaEmpleadoPorComision






9.4.2. Creación de una clase sin Circulo utilizando la herencia
Ahora analizaremos la segunda parte de nuestra introducción a la herencia por la que se declara y prueba (totalmente nueva e independiente) de clase Circulo (fig. 9,6), que contiene un nombre, apellido, número de seguro social, importe bruto de las ventas, la tasa de comisión y sueldo básico. De los servicios públicos de clase Circulo de incluir un constructor Circulo (líneas 1525) y los métodos de los ingresos (100.103 líneas) y toString (106.114 líneas). Líneas de 2897 declarar pública métodos get y set para las variables de instancia privada de la clase (declarada en las líneas 712) Nombre, Apellido, socialSecurityNumber, ventasTotales, commissionRate y baseSalary. Estas variables y métodos de encapsular todos los aspectos necesarios de una base-empleado de la Comisión asalariados. Tenga en cuenta la similitud entre esta clase y clase CommissionEmployee (Fig. 9.4) en este ejemplo, aún no se aprovecharán de que la similitud.




Figura 9.6. Circulo de clase representa a un empleado que recibe un sueldo base, además de una comisión.

// Fig. 9.6: EmpleadoBaseMasComision.java
// La clase EmpleadoBaseMasComision representa a un empleado que recibe
// un salario base, además de la comisión.

public class EmpleadoBaseMasComision
{
private String primerNombre;
private String apellidoPaterno;
private String numeroSeguroSocial;
private double ventasBrutas; // ventas totales por semana
private double tarifaComision; // porcentaje de comisión
private double salarioBase; // salario base por semana

// constructor con seis argumentos
public EmpleadoBaseMasComision( String nombre, String apellido,
String nss, double ventas, double tarifa, double salario )
{
// implicit call to Object constructor occurs here
primerNombre = nombre;
apellidoPaterno = apellido;
numeroSeguroSocial = nss;
establecerVentasBrutas( ventas ); // valida y almacena las ventas brutas
establecerTarifaComision( tarifa ); // valida y almacena la tarifa de comisión
establecerSalarioBase( salario ); // valida y almacena el salario base
} // fin del constructor de EmpleadoBaseMasComision con seis argumentos

// establece el primer nombre
public void establecerPrimerNombre( String nombre )
{
primerNombre = nombre;
} // fin del método establecerPrimerNombre

// devuelve el primer nombre
public String obtenerPrimerNombre()
{
return primerNombre;
} // fin del método obtenerPrimerNombre

// establece el apellido paterno
public void establecerApellidoPaterno( String apellido )
{
apellidoPaterno = apellido;
} // fin del métodoestablecerApellidoPaterno

// devuelve el apellido paterno
public String obtenerApellidoPaterno()
{
return apellidoPaterno;
} // fin del método obtenerApellidoPaterno

// establece el número de seguro social
public void establecerNumeroSeguroSocial( String nss )
{
numeroSeguroSocial = nss; // debe validar
} // fin del método establecerNumeroSeguroSocial

// devuelve el número de seguro social
public String obtenerNumeroSeguroSocial()
{
return numeroSeguroSocial;
} // fin del método obtenerNumeroSeguroSocial

// establece el monto de ventas brutas
public void establecerVentasBrutas( double ventas )
{
ventasBrutas = ( ventas < 0.0 ) ? 0.0 : ventas;
} // fin del método establecerVentasBrutas

// devuelve el monto de ventas brutas
public double obtenerVentasBrutas()
{
return ventasBrutas;
} // fin del método obtenerVentasBrutas

// establece la tarifa de comisión
public void establecerTarifaComision( double tarifa )
{
tarifaComision = ( tarifa > 0.0 && tarifa < 1.0 ) ? tarifa : 0.0;
} // fin del método establecerTarifaComision

// devuelve la tarifa de comisión
public double obtenerTarifaComision()
{
return tarifaComision;
} // fin del método obtenerTarifaComision

// establece el salario base
public void establecerSalarioBase( double salario )
{
salarioBase = ( salario < 0.0 ) ? 0.0 : salario;
} // fin del método establecerSalarioBase

// devuelve el salario base
public double obtenerSalarioBase()
{
return salarioBase;
} // fin del método obtenerSalarioBase

// calcula los ingresos
public double ingresos()
{
return salarioBase + ( tarifaComision * ventasBrutas );
} //fin del método ingresos

// devuelve representación String de EmpleadoBaseMasComision
public String toString()
{
return String.format(
"%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f",
"empleado por comision con sueldo base", primerNombre, apellidoPaterno,
"numero de seguro social", numeroSeguroSocial,
"ventas brutas", ventasBrutas, "tarifa de comision", tarifaComision,
"salario base", salarioBase );
} // find el método toString
} // fin de la clase EmpleadoBaseMasComision



Figura 9.7 pruebas de la clase EmpleadoBaseMasComision. 9 a 11 líneas de una instancia de un objeto EmpleadoBaseMasComision y pasan los argumentos "Bob", "Lewis", "333-33-3333", 5000, .04 y 300 para el constructor como el nombre, apellido, número de seguridad social, las ventas brutas, la tasa de comisión y el salario base, respectivamente. Líneas de 1627 el uso Circulo de obtener métodos para recuperar los valores de las variables de instancia del objeto para la salida. La línea 29 llama al método establecerRadio el objeto de modificar el sueldo básico. EstablecerRadio Método (Fig. 9.6, las líneas de 8891) asegura que baseSalary variable de instancia no se le asigna un valor negativo, porque el sueldo básico de un empleado no puede ser negativo. Líneas de 3133 de la figura. 9,7 invocar método toString del objeto de forma explícita para conseguir la representación de cadena del objeto.

Figura 9.7. Programa de pruebas EmpleadoBaseMasComision.


// Fig. 9.7: PruebaEmpleadoBaseMasComision.java
// Prueba de la clases EmpleadoBaseMasComision.

public class PruebaEmpleadoBaseMasComision
{
public static void main( String args[] )
{
// crea instancia de objeto EmpleadoBaseMasComision
EmpleadoBaseMasComision empleado =
new EmpleadoBaseMasComision(
"Bob", "Lewis", "333-33-3333", 5000, .04, 300 );

// obtiene datos del empleado por comisión con sueldo base
System.out.println(
"Informacion del empleado obtenida por metodos establecer: \n" );
System.out.printf( "%s %s\n", "El primer nombre es",
empleado.obtenerPrimerNombre() );
System.out.printf( "%s %s\n", "El apellido es",
empleado.obtenerApellidoPaterno() );
System.out.printf( "%s %s\n", "El numero de seguro social es",
empleado.obtenerNumeroSeguroSocial() );
System.out.printf( "%s %.2f\n", "Las ventas brutas son",
empleado.obtenerVentasBrutas() );
System.out.printf( "%s %.2f\n", "La tarifa de comision es",
empleado.obtenerTarifaComision() );
System.out.printf( "%s %.2f\n", "El salario base es",
empleado.obtenerSalarioBase() );

empleado.establecerSalarioBase( 1000 ); // establece el salario base

System.out.printf( "\n%s:\n\n%s\n",
"Informacion actualizada del empleado, obtenida por toString",
empleado.toString() );
} // fin de main
} // fin de la clase PruebaEmpleadoBaseMasComision






9.4.3. Creación de una jerarquía de herencia CommissionEmployeeBasePlusCommissionEmployee


Ahora declaramos BasePlusCommissionEmployee2 clase (fig. 9,8), que extiende la clase CommissionEmployee (Fig. 9.4). Un objeto BasePlusCommissionEmployee2 es un CommissionEmployee (porque la herencia pasa de las capacidades de la clase CommissionEmployee), pero BasePlusCommissionEmployee2 clase también tiene ejemplo baseSalary variable (fig. 9.8, línea 6). Palabra clave se extiende en la línea 4 de la declaración de la clase indica la herencia. Como una subclase, BasePlusCommissionEmployee2 hereda las variables de instancia pública y la protección y los métodos de la clase EmpleadoPorComision. El constructor de la clase CommissionEmployee no es hereditaria. Así, los servicios públicos de BasePlusCommissionEmployee2 incluir su constructor (líneas 916), los métodos públicos heredados de la clase CommissionEmployee, establecerRadio método (líneas 1922), getBaseSalary método (líneas 2528), los ingresos de método (líneas 3135) y el método toString (líneas 3847).



// Fig. 9.8: EmpleadoBaseMasComision2.java
// EmpleadoBaseMasComision2 hereda de la clase EmpleadoPorComision.

public class EmpleadoBaseMasComision2 extends EmpleadoPorComision
{
private double salarioBase; // salario base por semana

// constructor con seis argumentos
public EmpleadoBaseMasComision2( String nombre, String apellido,
String nss, double ventas, double tarifa, double salario )
{
// llamada explícita al constructor de la superclase EmpleadoPorComision
super( nombre, apellido, nss, ventas, tarifa );

establecerSalarioBase( salario ); // valida y almacena el salario base
} // fin del constructor de EmpleadoBaseMasComision2 con seis argumentos

// establecer salario base
public void establecerSalarioBase( double salario )
{
salarioBase = ( salario < 0.0 ) ? 0.0 : salario;
} // fin del método establecerSalarioBase

// devuelve el salario base
public double obtenerSalarioBase()
{
return salarioBase;
} // fin del método obtenerSalarioBase

// calcula los ingresos
public double ingresos()
{
// no está permitido: tarifaComision y ventasBrutas son private en la superclase
return salarioBase + ( tarifaComision * ventasBrutas );
} // fin del método ingresos

// devuelve representación String de EmpleadoBaseMasComision2
public String toString()
{
// no está permitido: intentos por acceder a los miembros private de la superclase
return String.format(
"%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f",
"empleado por comision con sueldo base", primerNombre, apellidoPaterno,
"numero de seguro social", numeroSeguroSocial,
"ventas brutas", ventasBrutas, "tarifa de comision", tarifaComision,
"salario base", salarioBase );
} // fin del método toString
} // fin de la clase EmpleadoBaseMasComision2




9.4.4. CommissionEmployeeBasePlusCommissionEmployee Jerarquía de herencia Usando protegidas variables de instancia
Para habilitar el Circulo de clase para acceder directamente a variables de instancia primerNombre superclase, apellido, socialSecurityNumber, ventasTotales y commissionRate, podemos declarar como protegidas a los miembros de la superclase. Como vimos en la sección 9.3, los miembros de una superclase protegidas son heredados por todas las subclases de la superclase. Clase CommissionEmployee2 (Fig. 9.9) es una modificación de la clase CommissionEmployee (fig. 9,4) que declara variables de instancia Nombre, Apellido, socialSecurityNumber, ventasTotales y commissionRate protegidas (Figura 9.9, las líneas 610) y no privado. Otros que el cambio en el nombre de clase (y por tanto el cambio en el nombre del constructor) a CommissionEmployee2, el resto de la declaración de clase en la figura. 9.9 es idéntica a la de la figura. 9.4.


Figura 9.9. CommissionEmployee2 con variables de instancia protected



// Fig. 9.9: EmpleadoPorComision2.java
// La clase EmpleadoPorComision2 representa a un empleado por comisión.

public class EmpleadoPorComision2
{
protected String primerNombre;
protected String apellidoPaterno;
protected String numeroSeguroSocial;
protected double ventasBrutas; // ventas totales por semana
protected double tarifaComision; // porcentaje de comisión

// constructor con cinco argumentos
public EmpleadoPorComision2( String nombre, String apellido, String nss,
double ventas, double tarifa )
{
// la llamada implícita al constructor del objeto ocurre aquí
primerNombre = nombre;
apellidoPaterno = apellido;
numeroSeguroSocial = nss;
establecerVentasBrutas( ventas ); // valida y almacena las ventas brutas
establecerTarifaComision( tarifa ); // valida y almacena la tarifa de comisión
} // fin del constructor de EmpleadoPorComision2 con cinco argumentos

// establece el primer nombre
public void establecerPrimerNombre( String nombre )
{
primerNombre = nombre;
} // fin del método establecerPrimerNombre

// devuelve el primer nombre
public String obtenerPrimerNombre()
{
return primerNombre;
} // fin del método obtenerPrimerNombre

// establece el apellido paterno
public void establecerApellidoPaterno( String apellido )
{
apellidoPaterno = apellido;
} // fin del método establecerApellidoPaterno

// devuelve el apellido paterno
public String obtenerApellidoPaterno()
{
return apellidoPaterno;
} // fin del método obtenerApellidoPaterno

// establece el número de seguro social
public void establecerNumeroSeguroSocial( String nss )
{
numeroSeguroSocial = nss; // debe validar
} // fin del método establecerNumeroSeguroSocial

// devuelve el número de seguro social
public String obtenerNumeroSeguroSocial()
{
return numeroSeguroSocial;
} // fin del método obtenerNumeroSeguroSocial

// establece el monto de ventas brutas
public void establecerVentasBrutas( double ventas )
{
ventasBrutas = ( ventas < 0.0 ) ? 0.0 : ventas;
} // fin del método establecerVentasBrutas

// devuelve el monto de ventas brutas
public double obtenerVentasBrutas()
{
return ventasBrutas;
} // fin del método obtenerVentasBrutas

// establece la tarifa de comisión
public void establecerTarifaComision( double tarifa )
{
tarifaComision = ( tarifa > 0.0 && tarifa < 1.0 ) ? tarifa : 0.0;
} // fin del método establecerTarifaComision

// devuelve la tarifa de comisión
public double obtenerTarifaComision()
{
return tarifaComision;
} // fin del método obtenerTarifaComision

// calcula los ingresos
public double ingresos()
{
return tarifaComision * ventasBrutas;
} // fin del método ingresos

// devuelve representación String del objeto EmpleadoPorComision2
public String toString()
{
return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f",
"empleado por comision", primerNombre, apellidoPaterno,
"numero de seguro social", numeroSeguroSocial,
"ventas brutas", ventasBrutas,
"tarifa de comision", tarifaComision );
} // fin del método toString
} // fin de la clase EmpleadoPorComision2




Clase BasePlusCommissionEmployee3 (Figura 9.10) es una modificación de BasePlusCommissionEmployee2 clase (fig. 9,8) que se extiende CommissionEmployee2 (línea 5) en lugar de la clase EmpleadoPorComision. Los objetos de BasePlusCommissionEmployee3 clase heredan las variables de instancia primerNombre CommissionEmployee2 está protegido, apellido, socialSecurityNumber, ventasTotales y commissionRateall estas variables están ahora protegidas miembros de BasePlusCommissionEmployee3. Como resultado, el compilador no genera errores al compilar la línea 32 de los ingresos de método y las líneas 4042 de método toString. Si otra clase se extiende BasePlusCommissionEmployee3, la nueva subclase hereda también los miembros protegidos.




// Fig. 9.10: EmpleadoBaseMasComision3.java
// EmpleadoBaseMasComision3 hereda de EmpleadoPorComision2 y tiene
// acceso a los miembros protected de EmpleadoPorComision2.

public class EmpleadoBaseMasComision3 extends EmpleadoPorComision2
{
private double salarioBase; // salario base por semana

// constructor con seis argumentos
public EmpleadoBaseMasComision3( String nombre, String apellido,
String nss, double ventas, double tarifa, double salario )
{
super( nombre, apellido, nss, ventas, tarifa );
establecerSalarioBase( salario ); // valida y almacena el salario base
} // fin del constructor de EmpleadoBaseMasComision3 con seis argumentos

// establece el salario base
public void establecerSalarioBase( double salario )
{
salarioBase = ( salario < 0.0 ) ? 0.0 : salario;
} // fin del método establecerSalarioBase

// devuelve el salario base
public double obtenerSalarioBase()
{
return salarioBase;
} // fin del método obtenerSalarioBase

// calcula los ingresos
public double ingresos()
{
return salarioBase + ( tarifaComision * ventasBrutas );
} // fin del método ingresos

// devuelve representación String de EmpleadoBaseMasComision3
public String toString()
{
return String.format(
"%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f",
"empleado por comision con salario base", primerNombre, apellidoPaterno,
"numero de seguro social", numeroSeguroSocial,
"ventas brutas", ventasBrutas, "tarifa comision", tarifaComision,
"salario base", salarioBase );
} // fin del método toString
} // fin de la clase EmpleadoBaseMasComision3




Figura 9.11 utiliza un objeto BasePlusCommissionEmployee3 para realizar las mismas tareas que la figura. 9,7 a cabo en un objeto Circulo (Fig. 9.6). Tenga en cuenta que los resultados de los dos programas son idénticos. A pesar de que declaró Circulo de clase sin necesidad de utilizar la herencia y declaró BasePlusCommissionEmployee3 clase mediante la herencia, ambas clases proporcionan la misma funcionalidad. El código fuente para BasePlusCommissionEmployee3 clase, que es de 45 líneas, es considerablemente más corto que el de la clase Circulo, que es de 115 líneas, porque BasePlusCommissionEmployee3 clase hereda la mayor parte de su funcionalidad desde CommissionEmployee2, mientras que la clase Circulo hereda la funcionalidad única clase de objetos. Además, ahora hay sólo una copia de la funcionalidad de empleado de la Comisión declaró en CommissionEmployee2 clase. Esto hace que el código sea más fácil de mantener, modificar y depurar, ya que el código relacionado con un empleado de la Comisión sólo existe en CommissionEmployee2 clase.



// Fig. 9.11: PruebaEmpleadoBaseMasComision3.java
// Prueba de la clase EmpleadoBaseMasComision3.

public class PruebaEmpleadoBaseMasComision3
{
public static void main( String args[] )
{
// crea instancia de un objeto EmpleadoBaseMasComision3
EmpleadoBaseMasComision3 empleadoBaseMasComision =
new EmpleadoBaseMasComision3(
"Bob", "Lewis", "333-33-3333", 5000, .04, 300 );

// obtiene datos del empleado por comision con sueldo base
System.out.println(
"Informacion del empleado, obtenida por los metodos establecer: \n" );
System.out.printf( "%s %s\n", "El primer nombre es",
empleadoBaseMasComision.obtenerPrimerNombre() );
System.out.printf( "%s %s\n", "El apellido es",
empleadoBaseMasComision.obtenerApellidoPaterno() );
System.out.printf( "%s %s\n", "El numero de seguro social es",
empleadoBaseMasComision.obtenerNumeroSeguroSocial() );
System.out.printf( "%s %.2f\n", "Las ventas brutas son",
empleadoBaseMasComision.obtenerVentasBrutas() );
System.out.printf( "%s %.2f\n", "La tarifa de comision es",
empleadoBaseMasComision.obtenerTarifaComision() );
System.out.printf( "%s %.2f\n", "El salario base es",
empleadoBaseMasComision.obtenerSalarioBase() );

empleadoBaseMasComision.establecerSalarioBase( 1000 ); // establece el salario base

System.out.printf( "\n%s:\n\n%s\n",
"Informacion actualizada del empleado, obtenida por toString",
empleadoBaseMasComision.toString() );
} // fin de main
} // fin de la clase PruebaEmpleadoBaseMasComision3







9.4.5. CommissionEmployeeBasePlusCommissionEmployee Jerarquía de herencia Usando las variables de instancia privada
Ahora volver a examinar nuestra jerarquía una vez más, esta vez utilizando las mejores prácticas de ingeniería de software. Clase CommissionEmployee3 (Figura 9.12) declara variables de instancia Nombre, Apellido, socialSecurityNumber, ventasTotales y commissionRate como privados (líneas 610) y proporciona setFirstName métodos públicos, getFirstName, setLastName, getLastName, setSocialSecurityNumber, getSocialSecurityNumber, setGrossSales, establecerY, setCommissionRate, getCommissionRate, las ganancias y toString para manipular estos valores. Tenga en cuenta que los métodos de los ingresos (8.588 líneas) y toString (líneas 9198) utiliza la clase de obtener métodos para obtener los valores de sus variables de instancia. Si decidimos cambiar el nombre de las variables ejemplo, los ingresos y declaraciones toString no requerirá modificationonly los cuerpos de los métodos get y set que manipular directamente las variables de instancia tendrá que cambiar. Tenga en cuenta que estos cambios se producen exclusivamente dentro de los cambios superclassno son necesarios para la subclase. La localización de los efectos de los cambios como éste es una buena práctica de ingeniería de software. Subclase BasePlusCommissionEmployee4 (Figura 9.13) hereda no CommissionEmployee3 de los métodos privados y pueden tener acceso a los miembros de la superclase privado a través de esos métodos.


// Fig. 9.12: EmpleadoPorComision3.java
// La clase EmpleadoPorComision3 representa a un empleado por comisión.

public class EmpleadoPorComision3
{
private String primerNombre;
private String apellidoPaterno;
private String numeroSeguroSocial;
private double ventasBrutas; // ventas totales por semana
private double tarifaComision; // porcentaje de comisión

// constructor con cinco argumentos
public EmpleadoPorComision3( String nombre, String apellido, String nss,
double ventas, double tarifa )
{
// la llamada implícita al constructor de Object ocurre aquí
primerNombre = nombre;
apellidoPaterno = apellido;
numeroSeguroSocial = nss;
establecerVentasBrutas( ventas ); // valida y almacena las ventas brutas
establecerTarifaComision( tarifa ); // valida y almacena la tarifa de comisión
} // fin del constructor de EmpleadoPorComision3 con cinco argumentos

// establece el primer nombre
public void establecerPrimerNombre( String nombre )
{
primerNombre = nombre;
} // fin del método establecerPrimerNombre

// devuelve el primer nombre
public String obtenerPrimerNombre()
{
return primerNombre;
} // fin del método obtenerPrimerNombre

// establece el apellido paterno
public void establecerApellidoPaterno( String apellido )
{
apellidoPaterno = apellido;
} // fin del método establecerApellidoPaterno

// devuelve el apellido paterno
public String obtenerApellidoPaterno()
{
return apellidoPaterno;
} // fin del método obtenerApellidoPaterno

// establece el número de seguro social
public void establecerNumeroSeguroSocial( String nss )
{
numeroSeguroSocial = nss; // debe validar
} // fin del método establecerNumeroSeguroSocial

// devuelve el número de seguro social
public String obtenerNumeroSeguroSocial()
{
return numeroSeguroSocial;
} // fin del método obtenerNumeroSeguroSocial

// establece el monto de ventas brutas
public void establecerVentasBrutas( double ventas )
{
ventasBrutas = ( ventas < 0.0 ) ? 0.0 : ventas;
} // fin del método establecerVentasBrutas

// devuelve el monto de ventas brutas
public double obtenerVentasBrutas()
{
return ventasBrutas;
} // fin del método obtenerVentasBrutas

// establece la tarifa de comisión
public void establecerTarifaComision( double tarifa )
{
tarifaComision = ( tarifa > 0.0 && tarifa < 1.0 ) ? tarifa : 0.0;
} // fin del método establecerTarifaComision

// devuelve la tarifa de comisión
public double obtenerTarifaComision()
{
return tarifaComision;
} // fin del método obtenerTarifaComision

// calcula los ingresos
public double ingresos()
{
return obtenerTarifaComision() * obtenerVentasBrutas();
} // fin del método ingresos

// devuelve representación String del objeto EmpleadoPorComision3
public String toString()
{
return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f",
"empleado por comision", obtenerPrimerNombre(), obtenerApellidoPaterno(),
"numero de seguro social", obtenerNumeroSeguroSocial(),
"ventas brutas", obtenerVentasBrutas(),
"tarifa de comision", obtenerTarifaComision() );
} // fin del método toString
} // fin de la clase EmpleadoPorComision3




Figura 9.13. Clase BasePlusCommissionEmployee4 extiende CommissionEmployee3, que prevé únicamente las variables de instancia privada ..


// Fig. 9.13: EmpleadoBaseMasComision4.java
// La clase EmpleadoBaseMasComision4 hereda de EmpleadoPorComision3 y
// accede a los datos private de EmpleadoPorComision3's a través de los
// métodos public de EmpleadoPorComision3.

public class EmpleadoBaseMasComision4 extends EmpleadoPorComision3
{
private double salarioBase; // salario base por semana

// constructor con seis argumentos
public EmpleadoBaseMasComision4( String nombre, String apellido,
String nss, double ventas, double tarifa, double salario )
{
super( nombre, apellido, nss, ventas, tarifa );
establecerSalarioBase( salario ); // valida y almacena el salario base
} // fin del constructor de EmpleadoBaseMasComision4 con seis argumentos

// establece el salario base
public void establecerSalarioBase( double salario )
{
salarioBase = ( salario < 0.0 ) ? 0.0 : salario;
} // fin del método establecerSalarioBase

// devuelve el salario base
public double obtenerSalarioBase()
{
return salarioBase;
} // fin del método obtenerSalarioBase

// calcula los ingresos
public double ingresos()
{
return obtenerSalarioBase() + super.ingresos();
} // fin del método ingresos

// devuelve representación String de EmpleadoBaseMasComision4
public String toString()
{
return String.format( "%s %s\n%s: %.2f", "con sueldo base",
super.toString(), "sueldo base", obtenerSalarioBase() );
} // fin del método toString
} // fin de la clase EmpleadoBaseMasComision4





Figura 9.14 realiza las mismas manipulaciones de un objeto BasePlusCommissionEmployee4 como lo hizo la figura. 9.7 y la figura. 9,11 en los objetos de las clases Circulo y BasePlusCommissionEmployee3, respectivamente. Aunque cada uno de "base-empleado de la Comisión asalariados" clase se comporta igual, BasePlusCommissionEmployee4 clase es la mejor ingeniería. Mediante el uso de la herencia y llamando a los métodos que se ocultan los datos y asegurar la coherencia, hemos de manera eficiente y eficaz construido una clase bien diseñada.

Figura 9.14. Superclase variables de instancia privada son accesibles a través de una subclase de métodos públicos o protegidos heredados por la subclase.




// Fig. 9.14: PruebaEmpleadoBaseMasComision4.java
// Prueba de la clase EmpleadoBaseMasComision4.

public class PruebaEmpleadoBaseMasComision4
{
public static void main( String args[] )
{
// crea instancia de un objeto EmpleadoBaseMasComision4
EmpleadoBaseMasComision4 empleado =
new EmpleadoBaseMasComision4(
"Bob", "Lewis", "333-33-3333", 5000, .04, 300 );

// obtiene datos del empleado por comisión con sueldo base
System.out.println(
"Informacion del empleado obtenida por los metodos establecer: \n" );
System.out.printf( "%s %s\n", "El primer nombre es",
empleado.obtenerPrimerNombre() );
System.out.printf( "%s %s\n", "El apellido es",
empleado.obtenerApellidoPaterno() );
System.out.printf( "%s %s\n", "El numero de seguro social es",
empleado.obtenerNumeroSeguroSocial() );
System.out.printf( "%s %.2f\n", "Las ventas brutas son",
empleado.obtenerVentasBrutas() );
System.out.printf( "%s %.2f\n", "La tarifa de comision es",
empleado.obtenerTarifaComision() );
System.out.printf( "%s %.2f\n", "El salario base es",
empleado.obtenerSalarioBase() );

empleado.establecerSalarioBase( 1000 ); // establece el salario base

System.out.printf( "\n%s:\n\n%s\n",
"Informacion actualizada del empleado, obtenida por toString",
empleado.toString() );
} // fin de main
} // fin de la clase PruebaEmpleadoBaseMasComision4

9.3. Miembros protected

En el aapítulo 8 hablamos sobre los modificadores de acceso públic y private. Los miembros públic de una clase son accesibles en cualquier parte que el programa tiene una referencia a un objeto de esa clase o una de sus subclases.Los Miembros private de una clase sólo son accesibles desde dentro de la propia clase.Los miembros privatede una superclase no son heredados por sus subclases. En esta sección, presentamos modificador de acceso protected. Utilizando el acceso protected ofrece un nivel intermedio de acceso entre públic y private. Miembros protected de una superclase pueden ser utilizados por los miembros de la superclase, por miembros de sus subclases y por los miembros de otras clases en el mismo paquete.

Todos los miembros de la superclase públic y protected retienen su modificador de acceso original, cuando se conviertan en miembros de la subclase.

Los métodos de una subclase puede referirse a los miembros públic y protected que se heredan de la superclase, simplemente utilizando los nombres de miembros. Cuando un método subclase sobreescribe al método de la superclase, este ultimo puede utilizarse desde la subclase si se antepone a su nombre la palabra clave super y punto (.)

9.2 Superclases y Subclases

A menudo, un objeto de una clase "es un" objeto de otra clase, así. Por ejemplo, en geometría, un rectángulo es un cuadrilátero (como son cuadrados, paralelogramos y trapecios). Por lo tanto, en Java, la clase rectángulo se puede decir que hereda de la clase cuadrilátero. En este contexto, la clase cuadrilátero es un superclase y la clase Rectangulo es una subclase.





Como todo objeto subclase "es un" objeto de su superclase, y como una superclase puede tener muchas subclases, el conjunto de los objetos representados por una superclase es normalmente mayor que el conjunto de los objetos representados por cualquiera de sus subclases. Por ejemplo, el vehículo superclase representa a todos los vehículos, incluyendo automóviles, camiones, barcos, bicicletas, etc. Por el contrario, la subclase coches representa a un subconjunto más pequeño,y específico de los vehículos


Las relaciones de herencia forman estructuras jerarquicas en forma de arbol. Una superclase existe en una relación jerárquica con sus subclases. Cuando las clases participar en las relaciones de herencia, se "afilan" con otras clases. Una clase se convierta en una superclase, proporcionando miembros a otras clases, o en una subclase, heredando sus mienbros de otras clases. En algunos casos, una clase es a la vez una superclase y una subclase.





domingo, 7 de febrero de 2010

PROGRAMACION ORIENTADA A OBJETOS: HERENCIA

9.1- Introduccion
9.2- Superclases y Subclases
9.3- Miembros protected
9.4- Relación entre superclases y subclases
9.5. Constructores en las subclases
9.6. Ingeniería de Software con herencia
9.7. Clase de objeto
9.8. (Opcional) GUI Estudio de caso: visualizacion de texto e imagenes
9.9. Wrap-Up


Introducción

En este capítulo se hablara acerca de la Programación Orientada Objetos (POO) y se introducirá una de sus características principales, la herencia, que es una forma de reutilización de software en la que se crea una nueva clase absorbiendo los miembros de una clase existente, y se mejoran con nuevas capacidades, o con modificaciones en las capacidades ya existentes. Con la herencia, los programadores ahorran tiempo durante el desarrollo, al reutilizar software probado y depurado de alta calidad. Esto también aumenta la probabilidad de que un sistema se implemente con efectividad.
Al crear una clase, en vez de declarar miembros completamente nuevos, el programador puede designar que la nueva clase herede los miembros de una clase existente. Esta clase existente se conoce como superclase, y la nueva clase se conoce como subclase. Cada subclase puede convertirse en la superclase de futuras subclases.
Una subclase generalmente agrega sus propios campos y métodos. Por lo tanto, una subclase es más específica que su superclase y representa un grupo más especializado de objetos. Generalmente, la subclase exhibe los comportamientos de su superclase junto con comportamiento adicionales específicos de esta subclase. Es por ello que la herencia se le conoce algunas veces como especialización.
La superclase directa es la superclase a partir de la cual la subclase hereda en forma explícita. Una superclase indirecta es cualquier clase arriba de la superclase directa en la jerarquía de clases, la cual define las relaciones de herencia entre las clases. En java, la jerarquía de clases empieza con la clase Object (en el paquete java.lang), a partir de cual se extienden (o “heredan”) todas las clases en Java, ya sea en forma directa o indirecta. En el caso de la herencia simple, una clase se deriva de una superclase directa.
Con la POO, los programadores se enfocan en los elementos comunes entre los objetos en el sistema, en vez de enfocarse en los casos especiales.
Es necesario hacer una diferencia entre la relación “es un” y la relación “tiene un”, La relación “es un” representa a la herencia. En este tipo de relación, un objeto de una subclase puede tratarse también como un objeto de su superclase. Por ejemplo, un automóvil es un vehículo. En contraste, la relación “tiene un” identifica a la composición. En este tipo de relación, un objeto contiene referencia a objetos como miembros. Por ejemplo, un automóvil tiene un volante de dirección (y un objeto automóvil tiene una referencia a un objeto volante de dirección).
Las clases nuevas pueden heredar de las clases en las bibliotecas de clases. Las organizaciones desarrollan sus propias bibliotecas de clase y pueden aprovechar las que ya están disponibles en todo el mundo. Es probable que algún día, la mayoría de software nuevo se construya a partir de componentes reutilizables estándar, como sucede actualmente con la mayoría de los automóviles y del hardware de computadora. Esto facilitaría el desarrollo de software más poderoso, abundante y económico.












Conclusión
En este capitulo se trato el concepto de herencia: la habilidad de crear clases mediante la absorción de los miembros de una clase existente, mejorándolos con nuevas capacidades. Se aprendió las nociones de las superclases y las subclases, y se utilizó la palabra clave extends para crear una subclase que hereda miembros de una superclase. En este capítulo se estudio el modificador de acceso protected; los métodos de la subclase pueden acceder a los miembros protected de la superclase. Se aprendió también como acceder a los miembros de la superclase mediante super. Se vio además cómo se utilizan los constructores en las jerarquías de herencia. Por último, se trato acerca de los métodos de la clase Object, la superclase directa o indirecta de todas las clases en Java.

Autoevaluación
9.1 Complete las siguientes oraciones:
a) ________________ es una forma de reutilización de software, en la que nuevas clases adquieren los miembros de las clases existentes, y se mejoran con nuevas capacidades.
b) Los miembros _______________ de una superclase pueden utilizarse en la declaración de la superclase y en las declaraciones de las subclases.
c) En una relación ______________, un objeto de una subclase puede ser tratado también como un objeto de su superclase.
d) En una relación _______________, el objeto de una clase tiene referencias a objetos de otras clases como miembros.
e) En la herencia simple, una clase existe en una relación _____________ con sus subclases.
f) Los miembros ______________ de una superclase son accesible en cualquier parte en donde el programa tenga una referencia a un objeto de esta superclase, a un objeto de una de sus subclases.
g) Cuando se crea la instancia de un objeto de una subclase, el _______________ de una superclase se llama en forma implícita o explícita.
h) Los constructores de una subclase puede llamar a los constructores de la superclase mediante la palabra clave _______________.
9.2 Conteste con verdadero o falso a cada una de las siguientes proposiciones; en caso de ser falso, explique por qué.
a) Los constructores de la superclase no son heredados por las subclases.
b) Una relación “tiene un” se implementa mediante la herencia.
c) Una clase Auto tiene una relación “es un” con las clases VolanteDirección y Frenos.
d) La herencia fomenta la reutilización de software comprobada, de alta calidad.
e) Cuando una subclase redefine al método de una superclase utilizando la misma firma, se dice que la subclase sobrecarga a ese método de la superclase.

Respuestas a los ejercicios de autoevaluación
9.1 a) Herencia. b) public y protected. c) “es un” o de herencia. d) “tiene-un” o composición. e) jerárquica. f) public. g) constructor. h) super.
9.2 a) Verdadero. b) Falso. Una relación “tiene un” se implementa mediante la composición. Una relación “es-un” se implementa mediante la herencia. c) Es falso. La clase Auto tiene una relación “es-un” con la clase vehiculo. d) Verdadero. e) Falso. Esto se conoce como sobrescritura, no sobrecarga; un método sobrecargado tiene el mismo nombre, pero una firma distinta.

Ejercicios
9.3 Muchos programas escritos con herencia podrían escribirse mediante la composición, y viceversa. Vuelve a escribir las clases EmpleadoBaseMasComision4 (figura 9.13) de la jerarquía EmpleadoPorComision3-EmpleadoBaseMasComision4 para usar la composición en vez de herencia. Una vez que haga esto, valore los méritos relativos de las dos metodologías para los problemas de EmpleadoPorComision3 y EmpleadoBaseMasComision4, así como también para los programas orientados a objetos en general. ¿Cuál metodología es más natural? ¿Por qué?
9.4 Describa las formas en las que la herencia fomenta la reutilización de software, ahorra tiempo durante el desarrollo de los programas y ayuda a prevenir errores.
9.5 Dibuje una jerarquía de herencia para los estudiantes en una universidad, de manera similar a la jerarquía que se muestra en la figura 9.2. Use a Estudiante como la superclase de la jerarquía, y después extienda Estudiante con las clases EstudianteNoGraduado y EstudianteGraduado. Siga extendiendo la jerarquía con el mayor número de niveles que sea posible. Por ejemplo, EstudiantePrimerAnio, EstudianteSegundoAnio, EstudianteTercerAnio y EstudianteCuartoAnio, podrían extender EstudianteNoGraduado, y EstudianteDoctorado y EstudianteMaestria podrían ser subclases de EstudianteGraduado. Después de dibujar la jerarquía, hable sobre las relaciones que existen entre las clase.