Alcance de las variables uso de "this"

Los parámetros de un método en una clase son conocidos como variables temporales. El valor y el nombre de estas variables expiran cuando el método llamado regresa el control al código que lo invocó. Cualquier variable definida en la lista de parámetros del método o dentro del cuerpo del método permanecen en memoria sólo lo que dura  en ejecutarse el método llamado.


En java existen cuatro tipos de variables:

Variables de Instancia (Campos No-Estáticos). Los objetos almacenan su estado individual en campos no-estáticos. Son declarados sin la palabra clave static. Sus valores son únicos para cada instancia u objeto.

Variables de Clase (Campos Estáticos). Son campos declarados con el modificador static (esta palabra debera estar definida para indicar este tipo de variables). Hay sólo una copia de esta variable para todas la instancias de la clase.

Variables Locales. Es en donde los métodos de los objetos almacenan su estado temporal. Se declaran parecido a los campos. No existe una palabra clave para especificar que una variable es local sino que depende donde la variable es declarada: dentro de los corchetes que definen un método. Son accesibles sólo dentro del método que las declaró y no son accesibles del resto de la clase.

Parámetros. Son las variables que conforman la firma de un método. Son siempre clasificados como variables y no como campos. También se encuentran en otras construcciones que aceptan parámetros como los son los constructores y manipuladores de excepciones.

El scope  ó alcance de las variable se refiere en que lugar del programa una variable específica puede ser usada o referenciada. Por lo general las variables pueden ser usada dentro del bloque de instrucciones al que pertenecen y no fuera de estos. Un bloque  se crea cada vez que tú abres y cierras corchetes ya sea para definir una clase, método o cualquier otra construcción. Más específicamente, el scope o alcance de una variable local abarca desde donde se declaró, hasta el corchete de cierre del bloque al que pertenecen El tiempo de vida de las variables depende del scope o alcance donde fueron declaradas. Sólo se puede declarar una vez una variable dentro de un bloque.

DEFINICION DE UNA CLASE

Una clase se define mediante la palabra Class y un nombre

class Deslizador{

// cuerpo de la clase

};

class DeslizadorDiapositivas extends  Deslizador {

// cuerpo de la clase

}


la palabra extends se usa para indicar la superclase de una clase

LAS VARIABLES LOCALES

Las variables locales se definen dentro de métodos.

public static void main (String [] arguments ) {

int total;

String Tituloinforme;

boolean activo;          //estan son varables locales ya que solo tienen ambito de acción entre los simbolos { }

}

esto se considera un metodo

LAS VARIABLES INSTANCIA

Se localizan en la definición de clase.

class PizarraHistoria extends PizarraHumanidades

{

String status;

int cantidad;

float puntuacion;

int numeroPrueba;    // definicion de variables instancia

}

VARIABLES DE CLASE

las variables de este tipo se aplican a la clase como un todo:


class PizarraHistoria extends PizarraHumanidades

{

String status;

int cantidad;

float puntuacion;

int numeroPrueba;    // definicion de variables instancia

static Int hora;

static final Int maxPruebas=10;  //definicion de variables de clase

}

METODOS

Se definen como comportamiento de los objetos

La definicion del métodos son cuatro partes:


Nombre

Parametros

Tipo devuelto

Cuerpo

La experiencia ha demostrado que la mejor manera de desarrollar y mantener un programa extenso es construirlo a partir de pequeñas piezas sencillas, o módulos.

Los métodos (también conocidos como funciones o procedimientos en otros lenguajes) permiten al programador dividir un programa en módulos, por medio de la separación de sus tareas en unidades autónomas. Usted ha declarado métodos en todos los programas que ha escrito. Las instrucciones en los cuerpos de los métodos se escriben sólo una vez, se ocultan de otros métodos y se pueden reutilizar desde varias ubicaciones en un programa.

Como sabe, un método se invoca mediante una llamada, y cuando el método que se llamó completa su tarea, devuelve un resultado, o simplemente el control al método que lo llamó. Una analogía a esta estructura de programa es la forma jerárquica de la administración. Un jefe (el solicitante) pide a un trabajador (el método llamado) que realice una tarea y que le reporte (devuelva) los resultados después de completar la tarea. El método jefe no sabe cómo el método trabajador realiza sus tareas designadas.


Tal vez el trabajador llame a otros métodos trabajadores, sin que lo sepa el jefe. Este “ocultamiento” de los detalles de implementación fomenta la buena ingeniería de software. La figura muestra al método jefe comunicándose con varios métodos trabajadores en forma jerárquica. El método jefe divide las responsabilidades entre los diversos métodos trabajador. Aquí trabajador actúa como “método jefe” de trabajador 4 y trabajador 5.



Para cualquier clase importada en su programa, puede llamar a cualquier método static especificando el nombre de la clase en la que está declarado el método, seguido de un punto (.) y del nombre del método, como sigue:

Nombre Clase.nonibreMétodo (argumentos)

System .out.println(Math.sqrt(900.0) );

En esta instrucción, el valor que devuelve sqrt se convierte en el argumento para el método println.

Los argumentos para los métodos pueden ser constantes, variables o expresiones. Si c = 13.0, d = 3 .0 y f = 4.0, entonces la instrucción

System .out.println(Math.sqrt(c + d * f ) );

calcula e imprime la raíz cuadrada de 13.0 + 3.0 * 4.0 = 2 5.0; a saber, 5.0


Métodos de la clase Math

para mas informacion vea:

https://docs.oracle.com/javase/6/docs/api/

Para dar a conocer estos conceptos haremos un programa que tenga el metodo y la clase:




El programa completo es:

package listarrango;

class ListarRango{ // inicio de la clase
// declaramos el metodo
    int [ ] crearRango(int inferior, int superior){ // inicio del metodo

// el tipo de retorno int [ ] es un array
// el nombre del metodo crearRango
// parametros int inferior, int superior

// sigue el cuerpo del metodo

int [ ]rango = new int[(superior - inferior)+1];
    for (int i = 0; i < rango.length; i++){ //inicio del for
   rango[i] = inferior++;
} //fin del for
return rango; //regresa un array el metodo
} // fin del metodo
  
  public static void main(String[] args) {
        int[ ] rango;
        ListarRango listar = new ListarRango(); // new ListarRango() nombre de la clase
                                                                    // objeto listar
        rango = listar.crearRango(5,15);           //pasamos los parametros al metodo
        System.out.println("El array  :");
                for (int i = 0; i < rango.length; i++){
                    System.out.print(rango[i]+ " ");
                }
    }
   
} //fin de la clase ListarRango

int [ ] crearRango(int inferior, int superior)

int [ ] = Tipo de retorno del método

crearRango = Nombre del método

(int inferior, int superior) = Parametros para recibir por el método

LA PALABRA CLAVE this

Hay ocasiones en las que resulta útil referirse al objeto desde el que se está ejecutando un método. En esas ocasiones se puede usar la referencia especial de objeto this, pero cuidado, siempre dentro de un método no estático.

Donde se usa:

En el cuerpo de definición de un método.


A que se refiere:

Al objeto que pertenece al método en el que se usa la palabra clave "this"

Para esto realizamos el ejemplo:


en la linea 8 hay una advertencia, e indica que hay una discrepancia entre la variables int test = 10;  corresponde a una variable instanciada de una clase (Palabrathis), y int test = 20; corresponde a una variable local, JAVA evalua de la parte interior hacia el exterior, y por lo que esta ultima variable oculta a la primera:





package palabrathis;

public class Palabrathis {
int test = 10; // es una variable instanciada de la clase

void imprimirTest (){ //metodo para imprimir la varaible local
    int test = 20; // es una variable local del metodo
    System.out.println("El valor de la variable local : "+test);
}
void imprimirThis (){ //metodo para imprimir la variable instanciada
    System.out.println("El valor de la variable instanciada "+this.test); //this.test solicita la variable this que es instanciada
//this solo actua sobre las variables instanciadas de clase
}   
    public static void main(String[] args) {
       Palabrathis st = new Palabrathis(); //creacion del objeto st
       st.imprimirTest(); //llamada al metodo imprimirTest
      
       Palabrathis st1 = new Palabrathis(); //creacion del metodo st1
       st1.imprimirThis(); //llamada al metodo imprimirThis             
    }
   
}

AñADIR PARAMETROS A METODOS


Hasta ahora habíamos visto como un método o constructor puede recibir parámetros de los tipos de datos primitivos en Java, como int, boolean, etc. e incluso de tipos envoltorio como Integer. Vamos a ver que también se pueden recibir otro tipo de parámetros.

Haremos un programa para demostrar como se pasan los argumentos al programa:

Hay que recordar como se pasan los argumentos al un programa:





Y el programa:




Puedes analizar y describir lo que hace el programa ?

package convertidor;
import java.lang.*;

public class Convertidor { // recibe los argumentos y reliza la conversion
void aMayusculas(String[] texto){  // de minusculas a mayusculas con toUpperCase
    for (int i =0;i<texto.length; i++){ // el ciclo revisa los argumentos
        texto[i] = texto[i].toUpperCase();
    }
       
}
  
    public static void main(String[] argumentos) { // en lugar de args esta argumentos
                                                                      // significa el nombre que le pasamos al array
                                                                      //podemos poner el nombre que sea.
        Convertidor convertidor = new Convertidor();
        convertidor.aMayusculas(argumentos);// aqui esta el nombre del array (argumentos)
        for (int i=0;i<argumentos.length; i++){
            System.out.print(argumentos[i]+" ");
        }
    }
   
}

APLICACIONES JAVA

Las aplicaciones son clases de Java, que se pueden ejecutar a ellas mismas.

Una aplicación Java estara formada por una o varias clases.

Una aplicación necesita una clase de inicio que tenga un método main().

public static void main (String [ ] arguments) {

// proceso

}

Las partes de esto son:  

public .-- Significa que esta disponible para otras clases y objetos.

static .- significa que el método main, es un método de clase.

void .-- no devolvera valor al termnimar el metodo, es decir los métodos usualmente devuelven algún valor, para void no regresa valor alguno.

(String [ ] arguments) .-- Toma un parametro que es un array



METODOS CON EL MISMO NOMBRE PERO CON DIFERENTES ARGUMENTOS.

La firma de un método es la combinación del tipo de dato que regresa, su nombre y su lista de argumentos. La sobrecarga de métodos es la creación de varios métodos con el mismo nombre pero con diferentes firmas y definiciones. Java utiliza el número y tipo de argumentos para seleccionar cuál definición de método ejecutar. Java diferencia los métodos sobrecargados con base en el número y tipo de argumentos que tiene el método y no por el tipo que devuelve. Tambien existe la sobrecarga de constructores: Cuando en una clase existen constructores múltiples, se dice que hay sobrecarga de constructores.

Pueden declararse métodos con el mismo nombre en la misma clase, siempre y cuando tengan distintos conjuntos de parámetros (que se determinan con base en el número, tipos y orden de los parámetros).

A esto se le conoce como sobrecarga de métodos. Cuando se hace una llamada a un método sobrecargado, el compilador de Java selecciona el método apropiado mediante un análisis del número, tipos y orden de los argumentos en la llamada. Por lo general, la sobrecarga de métodos se utiliza para crear varios métodos con el mismo nombre que realicen la misma tarea o tareas similares, pero con distintos tipos o números de argumentos.

Declaración de métodos sobrecargados

La clase SobrecargaMetodos incluye dos versiones sobrecargadas del método cuadrado:


una que calcula el cuadrado de un int (y devuelve un int) y otra que calcula el cuadrado de un double (y devuelve un double). Aunque estos métodos tienen el mismo nombre, además de listas de parámetros y cuerpos similares, podemos considerarlos simplemente como métodos diferentes. Puede ser útil si consideramos los nombres de los métodos como “cuadrado de i nt” y “cuadrado de double", respectivamente.




el resultado:


durante el proceso de escritura del codigo sse presentaran mensajes de error pero es normal ya que se llaman el metodos pero no esta, conforme se van creando los metodos los errores se van retirando.

Aqui el programa completo:

package sobrecargametodos;
/**
 * @author Miguel
 */
//prueba los metodos sobrecargados
public class SobreCargaMetodos {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       System.out.printf("El cuadrado del entero 7 es %d\n", cuadrado(7));
       System.out.printf("El cuadrado del double 7.5 es %f\n", cuadrado(7.5));
    } // fin de main
     // método cuadrado con argumento int
    public static int cuadrado(int valorInt)
    {
        System.out.printf("\n se llama al metodo cuadrado con int %d\n ", valorInt);
        return valorInt*valorInt;  // regresa el valor
    }                                        // fin del metodo con int
    // metodo cuadrado con argumento double
    public static double cuadrado(double valorDouble)
    {
        System.out.printf("\n se llama al metodos cuadrado con double %f\n", valorDouble);
        return valorDouble*valorDouble;
    }// fin del metodo double   
}


Cómo se diferencian los métodos sobrecargados entre si

El compilador diferencia los métodos sobrecargados con base en su firma: una combinación del nombre del método y del número, tipos y orden de sus parámetros. Si el compilador sólo se basara en los nombres de los métodos durante la compilación, el código anterior sería ambiguo; el compilador no "sabría" cómo distinguir entre los dos métodos cuadrado. De manera interna, el compilador utiliza nombres de métodos más largos que incluyen el nombre del método original, el tipo de cada parámetro y el orden exacto de ellos para determinar si los métodos en una clase son únicos en esa clase.

METODOS CONSTRUCTOR Y SOBREESCRITURA DE METODOS

Como sabe, puede declarar su propio constructor para especificar cómo deben inicializarse los objetos de una clase. A continuación demostraremos una clase con varios constructores sobrecargados, que permiten a los objetos de esa clase inicializarse de distintas formas. Para sobrecargar los constructores, sólo hay que proporcionar varias declaraciones del constructor con distintas firmas.

Los metodos constructor son llamandos de forma automatica cuando se crea un objeto.

Un método no puede ser llamado.

La palabra reservada para la creación de un objetos es NEW:

Localiza en la memoria una posición para el objeto creado.

Inicializa las variables instancia de un objeto.

Llama al método constructor de la clase.

Las ventajas de usar un método constructor:




El método constructor tendra el mismo nombre que la clase.

No tiene tipo de retorno.

No regresa valor por lo que no hay return.

Una clase puede tener mas de un costructor


la primer fase de estos es :

package circulo;

public class Circulo { //primer constructor con 3 parametros
int x,y,radio;
Circulo(int puntoX,int puntoY,int tamRadio ){ //aqui estan los 3 parametros
    this.x = puntoX;
    this.y = puntoY;
    this.radio = tamRadio;   
}
Circulo (int puntoX,int puntoY){ //segundo constructor con 2 parametros
    this(puntoX,puntoY,1); //relacionar los 2 cosntructor, esto los relaciona con el otro constructor
   
}
void Resultado(){
    int resultado = x*y*radio;
    System.out.println(resultado);
}

    public static void main(String[] args) {
 Circulo circulo = new Circulo(); //aqui se presenta un error porque solicitamos el metodo constructor
                                                 // pero hay 2 metodos por lo que es logico el error
(lo cambiamos por lo siguiente)

    Circulo circulo = new Circulo(2,3,1); // aqui definimos el metodos con el de 2 parametros o 3 parametros
                                                            // con ello estamos indicando en donde seran tomados
   
    }
   
}

si lo compilamos se ejecuta sin errores pero no veremos mingun nresulatdo porque no hemos solicitado la funcion void para mostrar el reultado para hacerlo veamos como modificamos, el programa, agregando la llamada desde el constructor (de hecho el constructor esta preparados para realizar esto).

al ejecutarlo el resultado sera:


esto se debe a que estamos solicitando el constructor con los 3 parametros y hemos colocado la llamada en el constructor en el que son 2 variables

package circulo;

public class Circulo { //primer constructor con 3 parametros
int x,y,radio;
Circulo(int puntoX,int puntoY,int tamRadio ){ //aqui estan los 3 parametros
    this.x = puntoX;
    this.y = puntoY;
    this.radio = tamRadio;
    Resultado();
}
Circulo (int puntoX,int puntoY){ //segundo constructor con 2 parametros
    this(puntoX,puntoY,1); //relacionar los 2 cosntructor, esto los relaciona con el otro constructor
    Resultado();
}
void Resultado(){
    int resultado = x*y*radio;
    System.out.println(resultado);
}
    public static void main(String[] args) {
    //Circulo circulo = new Circulo(); //aqui se presenta un error porque solicitamos el metodo constructor
                                     // pero hay 2 metodos por lo que es logico el error
    Circulo circulo = new Circulo(2,5); // aqui definimos el metodo con 2 parametros o 3 parametros
                                          // con ello estamos indicando en donde seran tomados
    }
   
}


Los métodos constructor se pueden sobrecargar.

Pueden declararse métodos con el mismo nombre en la misma clase, siempre y cuando tengan distintos conjuntos de parámetros (que se determinan con base en el número, tipos y orden de los parámetros).

A esto se le conoce como sobrecarga de métodos. Cuando se hace una llamada a un método sobrecargado, el compilador de Java selecciona el método apropiado mediante un análisis del número, tipos y orden de los argumentos en la llamada. Por lo general, la sobrecarga de métodos se utiliza para crear varios métodos con el mismo nombre que realicen la misma tarea o tareas similares, pero con distintos tipos o números de argumentos.

SOBRESCRIBIR METODOS

Un método se define en una subclase con la misma firma que un método de su Superclase

Realizaremos un programa en 2 partes para demostrar esto, usaremos la primera parte con una superclase y usando unas variables las "imprimiremos" y veremos que una tercera variable no se considera al mostrar el resultado, sobreescribimos el método para incluirla, crearemos un nuevo proyecto llamado Impresion, que vemos debajo.



Crear una clase llamada Imprimir:






Crear una clase llamada Subimprimir:


(decaramos e instanciamos la clase)

Primero modificaremos la classe Imprimir:


Modifiquemos la clase Subimprimir



y modifiquemos Impresion donde se encuentra la función main:



Realizemos un analisis de esto, en Impresion.java realiza una llamada a la clase Subimprimir que esta a su vez tiene como super clase a Imprimir.java, que su proposito es instanciar las variables x y, estableciendo método void imprimeme(), que muestra los valores de X y Y, mostrando la clase y el nombre, sin embargo en Subimprimir realiza herencia de Imprimir declarando z = 3, y esta no se puede mostrar ya que esta como elemento de la misma clase no de herencia, ejecutemos el programa:



pero si deseamos incluir el valor de z tendriams que modificar a Imprimir.java, pero no es necesrio solo modifiquemos a Subimprimir.java para que pueda ser incluido:


este método se llama sobreescritura de metodos, sin modificar las clases previas o superclase se agregan mas elememntos para el resultado, requerido.


Aqui los codigos:

IMPRESION.JAVA
-------------------------------------------------------------------
package impresion;

public class Impresion {

    public static void main(String[] args) {
        Subimprimir obj = new Subimprimir();
        obj.imprimeme();
    }
   
}

IMPRIMIR.JAVA
--------------------------------------------------------------------
package impresion;

public class Imprimir {
   int x = 0;
   int y = 1;

   void imprimeme()
   {
       System.out.println("X es :"+x+" y el valor de y es "+y);
       System.out.println("Soy una instancia de clase "+this.getClass().getName());
   }
}

SUBIMPRIMIR.JAVA
----------------------------------------------------------------------
package impresion;

public class Subimprimir extends Imprimir {
  int z = 3;
   void imprimeme(){
   System.out.println("X es :"+x+" y el valor de y es "+y+" z tiene el valor de "+z);
   System.out.println("Soy una instancia de clase "+this.getClass().getName());
   }  
}

Las razones para sobrescribir el método son:

1.- Reemplazar la definicion del método original completamente. (que fue lo que se realizo anteriormente)

2.- Ampliar el método original con comportamientos orignales. (para ello se usa la palabra clave super)

super es un contenerdor y se hace referencia a la superclase

(se realizo un programa, con la función super en el programa herencia1 del capitulo anterior)

MODIFICADORES Y CONTROL DE ACCESO

MODIFICADORES .- Son palabras clave se añaden a las definiciones, cambiando su significado

Los modificadores de acceso nos introducen al concepto de encapsulamiento.

El encapsulamiento busca de alguna forma controlar el acceso a los datos que conforman un objeto o instancia, de este modo podríamos decir que una clase y por ende sus objetos que hacen uso de modificadores de acceso (especialmente privados) son objetos encapsulados.

Los modificadores de acceso permiten dar un nivel de seguridad mayor a nuestras aplicaciones restringiendo el acceso a diferentes atributos, métodos, constructores asegurándonos que el usuario deba seguir una "ruta" especificada por nosotros para acceder a la información.

Es muy posible que nuestras aplicaciones vayan a ser usadas por otros programadores o usuarios con cierto nivel de experiencia; haciendo uso de los modificadores de acceso podremos asegurarnos de que un valor no será modificado incorrectamente por parte de otro programador o usuario. Generalmente el acceso a los atributos se consigue por medio de los métodos get y set, pues es estrictamente necesario que los atributos de una clase sean privados.

Nota 1: Siempre se recomienda que los atributos de una clase sean privados y por tanto cada atributo debe tener sus propios métodos get y set para obtener y establecer respectivamente el valor del atributo.

Nota 2: Siempre que se use una clase de otro paquete, se debe importar usando import. Cuando dos clases se encuentran en el mismo paquete no es necesario hacer el import pero esto no significa que se pueda acceder a sus componentes directamente.

La mayoría de las declaraciones de variables de instancia van precedidas por la palabra clave private. Al igual que public, la palabra clave prívate es un modificador de acceso. Las variables o los métodos declarados con el modificador de acceso private son accesibles sólo para los métodos de la clase en la que se declaran.

El proceso de declarar variables de instancia con el modificador de acceso private se conoce como ocultamiento de datos, u ocultamiento de información.

Las variables o métodos declarados con el modificador de acceso private sólo están accesibles para los métodos de la clase en la que están declarados.

El modificador public permite que todas las clases puedas acceder a estos métodos o variables.

El modificador protect.

El uso del acceso protected ofrece un nivel intermedio de acceso entre public y private. Los miembros protected de una superclase pueden ser utilizados por los miembros de esa superclase, por los de sus subclases y por los de otras clases en el mismo paquete; los miembros protected también tienen acceso a nivel de paquete.

Todos los miembros public y protected de una superclase retienen su modificador de acceso original cuando se convierten en miembros de la subclase (por ejemplo, los miembros public de la superclase se convierten en miembros public de la subclase, y los miembros protected de la superclase se vuelven en miembros protected de la subclase). Los miembros private de una superclase no pueden utilizarse fuera de la propia clase.

COMPARATIVA NIVELES DE ACCESO

Visible

public

protected

default

private

Desde la misma clase
Si
Si Si Si
Desde cualquier clase en el mismo paquete
Si Si Si No
Desde cualquier clase fuera del paquete
Si
No
No No
Desde una subclase en el mismo paquete
Si
Si Si No
Desde una  subclase fuera del mismo paquete.
Si
Si
No
No



Los métodos private no pueden ser heredados

MODIFICADOR PRIVATE

Ninguna otra clase puede recuperar varibles de este tipo de modificador

Veamos un ejemplo de esto:







package pruebacuenta;
import java.util.Scanner;

public class PruebaCuenta {

    public static void main(String[] args) {
    Cuenta cuenta1 = new Cuenta(50.00); // crea objeto Cuenta1
    Cuenta cuenta2 = new Cuenta(-7.53); // crea objeto Cuenta2
    //mostrar el saldo unicial de la cuenta 1 cuenta 2
    System.out.printf("saldo de cuenta 1: $%.2f\n", cuenta1.obtenerSaldo());
    System.out.printf("saldo de cuenta 2: $%.2f\n", cuenta2.obtenerSaldo());
    //crea objeto Scanner para obtener la entrada de la ventana de comandos
    Scanner entrada = new Scanner(System.in);
    double montoDeposito;
    System.out.print("El monto a depositar cuenta 1 ");
    montoDeposito = entrada.nextDouble();
    System.out.printf("\nsumando %.2f al saldo de cuenta 1\n\n",montoDeposito);
    cuenta1.abonar(montoDeposito);//suma a la cuenta 1
    //mostrar saldos
    System.out.printf("Saldo de la cuenta 1 %.2f\n ", cuenta1.obtenerSaldo());
    System.out.printf("Saldo de la cuenta 2 %.2f\n ", cuenta2.obtenerSaldo());
   
    System.out.print("El monto a depositar cuenta 2 ");
    montoDeposito = entrada.nextDouble();
    System.out.printf("\nsumando %.2f al saldo de cuenta 1\n\n ",montoDeposito);
    cuenta2.abonar(montoDeposito);//suma a la cuenta 2

    //mostrar saldos
    System.out.printf("Saldo de la cuenta 1 %.2f\n ", cuenta1.obtenerSaldo());
    System.out.printf("Saldo de la cuenta 2 %.2f\n ", cuenta2.obtenerSaldo());
   
    }
   
}



package pruebacuenta;

public class Cuenta {
   private double saldo; // variable de instancia que almacena el saldo
  //constructor
  public Cuenta (double saldoInicial)
  {
    // valida que saldo lnicial sea mayor que 0.0 ;
    // si no lo es, saldo se inicializa con el valor predeterminado 0.0
    if (saldoInicial > 0.0)
        saldo = saldoInicial;
   }// termina constructor
  // abona
  public void abonar (double monto)
  {
      saldo = saldo + monto;
  }
  // devuelve el saldo
  public double obtenerSaldo ()
  {
      return saldo;
      // proporciona el valor de saldo al método que hizo la llamada
  }
}

MODIFICADOR STATIC

Un método static es especial, ya que puede llamarse sin tener que crear primero un objeto de la clase en la cual se declara ese método.

Aunque la mayoría de los métodos se ejecutan en respuesta a las llamadas a métodos en objetos específicos, éste no es siempre el caso. Algunas veces un método realiza una tarea que no depende del contenido de ningún objeto. Dicho método se aplica a la clase en la que está declarado como un todo, y se conoce como método static o método de clase. Es común que las clases contengan métodos static convenientes para realizar tareas comunes, coloque la palabra clave static antes del tipo de valor de retorno en la declaración del método.

Para cualquier clase importada en su programa, puede llamar a cualquier método static especificando el nombre de la clase en la que está declarado el método, seguido de un punto (.) y del nombre del método, como sigue:

Nombre Clase. nombreMétodo ( argumentos )

Ejemplo de modificador static





La declaración del método maximo comienza con la palabra clave public para indicar que el método está “disponible para el público”: puede llamarse desde los métodos de otras clases. La palabra clave static permite al método main (otro método static) llamar a maximo, como se muestra, sin tener que calificar el nombre del método con el nombre de la clase buscadorMaximo; los métodos static en la misma clase pueden llamarse unos a otros de manera directa. Cualquier otra clase que utilice a máximo debe calificar por completo el nombre del método, con el nombre de la clase.

Considere la declaración del método maximo. La línea 24 indica que el método devuelve un valor double, que el nombre del método es máximo y requiere tres parámetros double (x, y y z) para realizar su tarea. Los parámetros múltiples se especifican como una lista separada por comas. Cuando se hace la llamada a máximo en la línea 24, los parámetros x, y y z se inicializan con los valores de los argumentos numerol, numero2 y numero3, respectivamente.

Hay tres formas de llamar a un método:


1. Utilizar el nombre de un método por sí solo para llamar a otro método de la misma clase; como maximo (numerol, numero2, numero3).

2. Usar una variable que contiene una referencia a un objeto, seguida de un punto (.) y del nombre del método para llamar a un método no static del objeto al que se hace referencia; como la llamada al método.

3. Utilizar el nombre de la clase y un punto (.) para llamar a un método static de una clase, como Math. sqrt( 900.0 ).

Un método static sólo puede llamar directamente a otros métodos static de la misma clase (es decir, mediante el nombre del método por sí solo) y sólo puede manipular de manera directa variables static en la misma clase. Para acceder a los miembros no static de la clase, un método static debe usar una referencia a un objeto de esa clase. Recuerde que los métodos static ese relacionan con una clase como un todo, mientras que los métodos no static se asocian con una instancia específica (objeto) de la clase y pueden manipular las variables de instancia de ese objeto.

Método Accesor

class ReverseString {
    public static String reverseIt(String source) {
        int i, len = source.length();
        StringBuffer dest = new StringBuffer(len);

        for (i = (len - 1); i >= 0; i--) {
            dest.append(source.charAt(i));
        }
        return dest.toString();
    }
}

Revisando este fragmento de codigo,

Las variables de ejemplar de un objeto están encapsuladas dentro del objeto, ocultas en su interior, seguras frente a la inspección y manipulación por otros objetos.


Con ciertas excepciones bien definidas, los métodos del objeto no son los únicos a través de los cuales un objeto puede inspeccionar o alterar las variables de otro objeto.
La encapsulación de los datos de un objeto lo protege de la corrupción de otros objetos y oculta los detalles de implementación a los objetos extraños. Esta encapsulación de datos detrás de los métodos de un objeto es una de las piedras angulares de la programación orientada a objetos.
Los métodos utilizados para obtener información de un objeto son conocidos como métodos accesores.

El método reverseIt() utiliza dos métodos accesores de String para obtener información sobre el string source.

Primero utiliza el método accesor: length() para obtener la longitud de la cadena source.

int len = source.length();

Observa que a reverseIt() no le importa si el String mantiene su longitud como un entero, como un número en coma flotante o incluso si calcula la longitud al vuelo. reverseIt() simplemente utiliza el interface público del método length() que devuelve la longitud del String como un entero. Es todo lo que necesita saber reverseIt().

Segundo, utiliza el método accesor: charAt() que devuelve el carácter que está situado en la posición indicada en su argumento.

source.charAt(i)

El carácter devuelto por charAt() es el que se añade al StringBuffer dest. Como la variable del bucle i empieza al final de source y avanza hasta el principio de la cadena, los caracteres se añaden en orden inverso al StringBuffer.

MODIFICADOR PROTECTED

El uso del acceso protected ofrece un nivel intermedio de acceso entre public y private. Los miembros protected de una superclase pueden ser utilizados por los miembros de esa superclase, por los de sus subclases y por los de otras clases en el mismo paquete; los miembros protected también tienen acceso a nivel de paquete.


Todos los miembros public y protected de una superclase retienen su modificador de acceso original cuando se convierten en miembros de la subclase (por ejemplo, los miembros public de la superclase se convierten en miembros public de la subclase, y los miembros protected de la superclase se vuelven en miembros protected de la subclase). Los miembros private de una superclase no pueden utilizarse fuera de la propia clase. En cambio, están ocultos en sus subclases y se pueden utilizar sólo a través de los métodos public o protected heredados de la superclase.

Los métodos de una subclase pueden referirse a los miembros public y protected que se hereden de la superclase con sólo utilizar los nombres de los miembros. Cuando un método de la subclase sobrescribe al método heredado de la superclase, éste último puede utilizarse desde la subclase si se antepone a su nombre la palabra clave super y un punto (.) separador.

Declarar variables de instancia private ayuda a los programadores a probar, depurar y modificar correctamente los sistemas. Si una subclase puede acceder a las variables de instancia prívate de su superclase, las clases que hereden de esa subclase podrían acceder a las variables de instancia también. Esto propagaría el acceso a las que deberían ser variables de instancia private , y se perderían los beneficios del ocultamiento de la información.





package pruebaempleadoporcomision;
public class PruebaEmpleadoPorComision {
    public static void main(String[] args) {
        // crea instancia de objeto EmpleadoPorComision
       EmpleadoPorComision empleado = new EmpleadoPorComision("Sue","Jones","222-22-2222",10000,0.06);
      // obtiene datos del empleado por comisión
      System.out.println("Información del empleado obtenida por los métodos establecer: \n ");
      System.out.printf("%s %s\n","El primer nombre es ",empleado.getPrimerNombre());
      System.out.printf("%s %s\n","El apellido paterno es :",empleado.getApellidoPaterno());
      System.out.printf("%s %s\n","El numero de Seguro Social",empleado.getNumeroSeguroSocial());
      System.out.printf("%s %.2f\n","Las ventas brutas son ",empleado.getVentasBrutas());
      System.out.printf("%s %.2f","La tarifa de comision es ",empleado.getTarifaComision());
     
      empleado.setVentasBrutas(500);
      empleado.setTarifaComision(.1);
     
      System.out.printf("\n%s : \n\n%s\n","Informacion actualizada del empleado obtenida mediante "
              + "toString ",empleado);
    }//fin de main
}//fin de la clase













Aqui el programa, la clase y la clase objet

PruebaEmpleadoPorComision

--------------------------------------------
package pruebaempleadoporcomision;
public class PruebaEmpleadoPorComision {
    public static void main(String[] args) {
        // crea instancia de objeto EmpleadoPorComision
       EmpleadoPorComision empleado = new EmpleadoPorComision("Sue","Jones","222-22-2222",10000,0.06);
      // obtiene datos del empleado por comisión
      System.out.println("Información del empleado obtenida por los métodos establecer: \n ");
      System.out.printf("%s %s\n","El primer nombre es ",empleado.getPrimerNombre());
      System.out.printf("%s %s\n","El apellido paterno es :",empleado.getApellidoPaterno());
      System.out.printf("%s %s\n","El numero de Seguro Social",empleado.getNumeroSeguroSocial());
      System.out.printf("%s %.2f\n","Las ventas brutas son ",empleado.getVentasBrutas());
      System.out.printf("%s %.2f","La tarifa de comision es ",empleado.getTarifaComision());
     
      empleado.setVentasBrutas(500);
      empleado.setTarifaComision(.1);
     
      System.out.printf("\n%s : \n\n%s\n","Informacion actualizada del empleado obtenida mediante "
              + "toString ",empleado);
    }//fin de main
}//fin de la clase

EmpleadoPorComision

---------------------------------------
package pruebaempleadoporcomision;
public class EmpleadoPorComision extends Objet //realizar la clase Objet (vacio)
{
private String PrimerNombre;
private String ApellidoPaterno;
private String NumeroSeguroSocial;
private double VentasBrutas;
private double TarifaComision;

//constructor con 5 argumentos
public EmpleadoPorComision(String Nombre,String Apellido, String nss,double ventas,double tarifa)
{
 // la llamada implícita al constructor de Object ocurre aqui
 PrimerNombre = Nombre;
 ApellidoPaterno = Apellido;
 NumeroSeguroSocial = nss;
 setVentasBrutas (ventas);// valida y almacena las ventas brutas
 setTarifaComision (tarifa);// valida y almacena la tarifa de comisión
 
}// fin del constructor de EmpleadoPorComision con cinco argumentos

// establece el primer nombre
public void setPrimerNombre (String Nombre)
{
    PrimerNombre = Nombre;
}
// recupera el nombre
public String getPrimerNombre()
{
    return PrimerNombre;
}
// establece el apellido
public void setApellidoPaterno (String Apellido)
{
    ApellidoPaterno =Apellido;
}
//recupera el apellido
public String getApellidoPaterno ()
{
    return ApellidoPaterno;
}
// establece el número de seguro social
public void setNumeroSeguroSocial (String nss)
{
    NumeroSeguroSocial = nss;
}
//regresa el valor del numero de seguro social
public String getNumeroSeguroSocial()
{
    return NumeroSeguroSocial;
}
// establece del monto de venta
public void setVentasBrutas (double ventas)
{
    if (ventas >= 0.0)
    VentasBrutas = ventas;
    else
    {
     throw new IllegalArgumentException
     ( "Las ventas brutas deben ser mayores o igual a 0.0" );  
    }
}
//regresa el valor de ventas
public double getVentasBrutas()
{
return VentasBrutas;   
}
//establecer la tarifa de comision
public void setTarifaComision (double tarifa)
{
    if (tarifa >0.0 && tarifa <1.0)
        TarifaComision = tarifa;
    else
    {
        throw new IllegalArgumentException
        (
        "La tarifa de comision de be ser mayor a 0.0 y menor a 0.0"
        );
    }
}   
   //devuelve la tarifa comision
   public double getTarifaComision()
   {
       return TarifaComision;
   }
   // calcula ingresos
   public double ingresos()
   {
       return TarifaComision * VentasBrutas;
   }       
   // devuelve representación String del objeto EmpleadoPorComision
 
@Override //indica que este método sobrescribe el método de una superclase

   public String toString()
   {       
    return String.format("%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f ",
           "empleado por comisión",PrimerNombre,ApellidoPaterno,
           " numero de seguro social ",NumeroSeguroSocial,
           " ventas brutas ",VentasBrutas,
           " tarifa de comisión",TarifaComision);
   }
}

Objet

------------------------------
package pruebaempleadoporcomision;

/**
 *
 * @author Miguel
 */
class Objet {
   
}

@Override

Si una clase base de Java tiene un nombre de método varias veces sobrecargado, redefinir dicho nombre en la clase derivada no ocultará la implementación en ninguna de las versiones de la clase base (a diferencia de lo que sucede en C++). Por lo tanto, el mecanismo de sobrecarga funciona independientemente de si el método ha sido definido en este nivel o en una clase base.


Lo más común es sobrecargar los métodos del mismo nombre, utilizando exactamente la misma signatura y el mismo tipo de retorno. En caso contrario, el código podría resultar confuso (lo cual es la razón por la que C++ oculta todos los métodos de la clase base, para que no cometamos lo que muy probablemente se trata de un error).


Java ha añadido al lenguaje la anotación @Override, que no es una palabra clave pero puede usarse como si lo fuera. Cuando queremos sustituir un método, esa es la razon que agregamos public class EmpleadoPorComision extends Objet donde Objet, será la extension de @Override podemos añadir esta anotación y el compilador generará un mensaje de error si sobrecargamos accidentalmente el método en lugar de sustituirlo.

La anotación @Override evitará, así, que sobrecarguemos accidentalmente un método cuando no es eso lo que queremos hacer.

MODIFICADOR FINAL

Cuando necesitamos que el valor de un atributo no cambie durante el transcurso de nuestro programa, debemos utilizar el modificador final en su definición de la siguiente manera:

public final float pi = 3.14f;

En este ejemplo utilizamos el modificador final para almacenar el valor de la constante matemática pi, ya que su valor nunca va a cambiar, si por error intentásemos modificar el valor de un atributo definido como final, el compilador nos notificaría un error.

Además, muchas veces los modificadores static y final se utilizan en conjunto para definir constantes como puedes ver en el siguiente ejemplo:

public class Constantes {
     //Constantes publicas
     public static final float PI = 3.141592f;
     public static final float E = 2.728281f;
     //MAIN
     public static void main(String[] args) {
          System.out.println("PI = " + Constantes.PI);
          System.out.println("E = " + Constantes.E);
     }
}

Definiendo un atributo como public, static y final, obtenemos una constante que podrá ser accedida desde cualquier clase (public), el acceso se podrá realizar sin tener que instanciar la clase mediante el nombre de la clase (static) y su valor no podrá ser modificado en ningún momento (final).

El modificador final también se puede utilizar sobre un método o una clase (tema de la herencia).

Para las clases también puede usarse final como:

public final void getDatosUsuario()
{
// instrucciones
}

esto es para que la clase se vuelva mas rápida, pero  se aconseja  usarla cuando ya se hayan realizado las pruebas y funcionalidad, requiriendo mas velocidad se aplica, y no afecta los procesos, clases, subcalses, etc.

Ejercicio.-  pruebe establecer el modificador final en los métodos el IDE de NetBeans le mostrara si la instrucción esta en el lugar correcto.

POLIMORFISMO

Ahora explicaremos y demostraremos el polimorfismo con las jerarquías de herencia. 

El polimorfismo nos permite “programar en forma general”, en vez de “programar en forma específica.” 

En particular, nos permite escribir programas que procesen objetos que compartan la misma superclase (ya sea de manera directa o indirecta) como si todos fueran objetos de la superclase; esto puede simplificar la programación. Considere el siguiente ejemplo de polimorfismo. Suponga que crearemos un programa que simula el movimiento de varios tipos de animales para un estudio biológico. Las clases Pez, Rana y Ave representan los tipos de animales que se están investigando. Imagine que cada una de estas clases extiende a la superclase Animal, la cual contiene un método llamado mover y mantiene la posición actual de un animal, en forma de coordenadas x-y. Cada subclase implementa el método mover. Nuestro programa mantiene un arreglo tipo Animal, de referencias a objetos de las diversas subclases de Animal. 

Para simular los movimientos de los animales, el programa envía a cada objeto el mismo mensaje una vez por segundo; mover. Cada tipo específico de Animal responde a un mensaje mover de manera única; un Pez podría nadar tres pies, una Rana, saltar cinco pies y un Ave, volar diez pies.

Cada objeto sabe cómo modificar sus coordenadas x-y en forma apropiada para su tipo específico de movimiento. 

Confiar en que cada objeto sepa cómo “hacer lo correcto” (es decir, lo que sea apropiado para ese tipo de objeto) en respuesta a la llamada al mismo método es el concepto clave del polimorfismo. El mismo mensaje (en este caso, mover) que se envía a una variedad de objetos tiene “muchas formas” de resultados; de aquí que se utilice el término polimorfismo.

El polimorfismo promueve la extensibilidad: el software que invoca el comportamiento polimórfico es independiente de los tipos de los objetos a los cuales se envían los mensajes.

Es posible incorporar en un sistema nuevos tipos de objetos que puedan responder a las llamadas de los métodos existentes, sin necesidad de modificar el sistema base. Sólo el código cliente que crea instancias de los nuevos objetos debe modificarse para dar cabida a los nuevos tipos.

El propósito de una clase abstracta es proporcionar una superclase apropiada, a partir de la cual puedan heredar otras clases y, por ende, compartir un diseño común.

Para hacer una clase abstracta, ésta se declara con la palabra clave abstract. Por lo general, esta clase contiene uno o más métodos abstractos, cada uno con la palabra clave abstract en su declaración, como en:


public abstract void dibujar (); / / método abstracto

Los métodos abstractos no proporcionan implementaciones. Una clase que contiene uno o más métodos abstractos debe declararse de manera explícita como abstract, aun si esa clase contiene métodos concretos (no abstractos).

Situación  a trabajar:

Una compañía paga semanalmente a sus empleados, quienes se dividen en cuatro tipos: 

Empleados asalariados que reciben un salario semanal jijo, sin importar el número de horas trabajadas; 

Empleados por horas, que perciben un sueldo por hora y pago por tiempo extra (es decir, 1.5 veces la tarifa de su salario por horas), por todas las horas trabajadas que excedan a 40 horas; 

Empleados por comisión, que perciben un porcentaje de sus ventas

 Empleados asalariados por comisión, que obtienen un salario base más un porcentaje de sus ventas. 

Para este periodo de pago, la compañía ha decidido recompensar a los empleados asalariados por comisión, agregando un 10% a sus salarios base. La compañía desea implementar una aplicación que realice sus cálculos de nómina en firma polimórfico.



Estructura del programa

La superclase abstracta Empleado declara la “interfaz” para la jerarquía; esto es, el conjunto de métodos que puede invocar un programa en todos los objetos Empleado. Aquí utilizamos el término “interfaz” en un sentido general, para referirnos a las diversas formas en que los programas pueden comunicarse con los objetos de cualquier subclase de Empleado. Tener cuidado de no confundir la noción general de una “interfaz” con la noción formal de una interfaz en Java.




Interfaz polimórfica para las clases de la jerarquía de Empleado.



// superclase abstracta Empleado
package empleado;

public abstract class Empleado {
    private String PrimerNombre;
    private String ApellidoPaterno;
    private String NumeroSeguroSocial;
 
    //constructor con 3 argumentos
    public Empleado(String Nombre,String Apellido, String Nss)
    {
        PrimerNombre = Nombre;
        ApellidoPaterno = Apellido;
        NumeroSeguroSocial = Nss;
    }  //fin del constructor
   
    //establece el primer nombre
    public void setPrimerNombre(String Nombre)
    {
        PrimerNombre = Nombre;
    }
    //devuelve el primer nombre
    public String getPrimerNombre()
    {
        return PrimerNombre;
    }
    // establece Apellido
    public void setApellidoPaterno (String Apellido)
    {
       ApellidoPaterno = Apellido;
    }
    // devulve el apellido
    public String getApellidoPaterno()
    {
        return ApellidoPaterno;
    }
    // establece el nss
    public void setNumeroSeguroSocial(String Nss)
    {
        NumeroSeguroSocial = Nss;
    }
    // devulve el numero de seguro social
    public String getNumeroSeguroSocial()
    {
        return NumeroSeguroSocial;
    }
    // devuelve representación String de un objeto Empleado
   
    @Override
    public String toString()
    {
        return String.format("%s %s\nnumero de seguro social: %s",getPrimerNombre(),getApellidoPaterno(),getNumeroSeguroSocial());
    }
    // método abstracto sobre escrito por la s subclases concretas
    public abstract double Ingresos();
}

La subclase concreta EmpleadoAsalariado extiende a la clase Empleado y sobrescribe el método abstracto ingresos, lo cual convierte a EmpleadoAsalariado en una clase concreta.





// La clase concreta Empleado Asalariado extiende a laclase abstracta Empleado.
package empleado;
public class EmpleadoAsalariado extends Empleado
{
private double SalarioSemanal;
//constructor de 4 argumentos
public EmpleadoAsalariado(String Nombre,String Apellido, String Nss, double Salario)
{
 super (Nombre,Apellido,Nss); //pasa al constructor del Empleado
 setSalarioSemanal (Salario); //valida y almacena
}// termina el constructor
//establece el salario
public void setSalarioSemanal(double Salario)
{
    if (Salario >= 0.0)
    {SalarioSemanal = Salario;}
   else
    { throw new IllegalArgumentException(" El salario Semannal debe ser mayor a 0.0 ");}
}// fin del metodo setSalarioSemanal
// regresa salario

public double getSalarioSemanal()
{
    return SalarioSemanal;
}
// calcula los ingresos:sobrescribe el método abstracto ingresos en Empleado
@Override
public double Ingresos()
 {
 return getSalarioSemanal();        
 }
// devuelve representación String de un objeto EmpleadoAsalariado
 
@Override
public String toString()
{
    return String.format(" empleado asalriado : %s\n%s: $%,.2f",super.toString(),"salario semanal",getSalarioSemanal());
}
}


La subclase concreta EmpleadoPorHoras

La clase EmpleadoPorHoras también extiende a Empleado (es uan subclase). La clase incluye un constructor que recibe como argumentos un primer nombre, un apellido paterno, un número de seguro social, un sueldo por horas y el número de horas trabajadas. Se declaran los métodos set que asignan nuevos valores a las variables de instancia sueldo y horas. El método setSueldo asegura que sueldo sea no negativo, y el método setHoras asegura que horas esté entre 0 y 168 (el número total de horas en una semana), ambos valores inclusive. La clase EmpleadoPorHoras también incluye métodos get, para devolver los valores de sueldo y horas, respectivamente; un método ingresos para calcular los ingresos de un EmpleadoPorHoras; y un método toString, que devuelve un objeto String con el tipo del empleado (“ empleadoporhoras: ”), e información específica para ese Empleado. El constructor de EmpleadoPorHoras, al igual que el constructor de EmpleadoAsalariado, pasa el primer nombre, el apellido paterno y el número de seguro social al constructor de la superclase Empleado para inicializar las variables de instancia private.

Además, el método toString llama al método toString de la superclase para obtener la información específica del Empleado (es decir, primer nombre, apellido paterno y número de seguro social); éste es otro excelente ejemplo de reutilización de código.




// La clase EmpleadoPorHoras extiende a Empleado.
package empleado;

public class EmpleadoPorHoras extends Empleado{
 
    private double Sueldo; //sueldo por horas
    private double Horas; //horas trabajadas por semana
   
    //constructor
    public EmpleadoPorHoras (String Nombre,String Apellido,String Nss,double SueldoPorHoras,double HorasTrabajadas)
    {
    super(Nombre,Apellido,Nss);
    setSueldo(SueldoPorHoras); // valida y almacena el sueldo por horas
    setHoras(HorasTrabajadas); // valida y almacena Horas trabajadas
      
    }//fin del constructor
   
    // establece sueldo
    public void setSueldo (double SueldoPorHoras)
    {
        if (SueldoPorHoras >= 0.0)
            Sueldo = SueldoPorHoras;
        else
        {
            throw new IllegalArgumentException ("El sueldo debe ser mayor o igual a 0.0 ");
        }
    }//fin de metodos setSueldo
   
    //devuelve el sueldo
    public double getSueldo()
    {
        return Sueldo;
    } //termina metodos regresa sueldo
   
    //establece horas trabajadas
    public void setHoras (double HorasTrabajadas)
    {
        if((HorasTrabajadas >= 0.0) && (HorasTrabajadas <=168))
            Horas = HorasTrabajadas;
        else
        {
          throw new IllegalArgumentException("Las horas trabajadas deben ser mayor o igual a 0.0 o menor o igual que 168");
        }
    }//fin del metodo HorasTrabajadas
   
    //devulve las horas trabajadas
   
    public double getHoras()
    {
        return Horas;
    }
   
  // calcula los ingresos; sobrescribe el método abstracto ingresos en Empleado
   
  public double Ingresos ()
  {
      if (getHoras() <= 40) // no aplica para tiempo extra
          return getSueldo() * getHoras();
      else
      {
        return 40*getSueldo()+(getHoras() -40)*getSueldo()*1.5; 
      }
  } //fin metodo ingresos
  // devuelve representación String de un objeto EmpleadoPorHoras
 
    @Override
  public String toString()
  {
      return String.format("empleado por horas: %s\n%s: $%,.2f; %s: %,.2f",super.toString(),"sueldo por hora",getSueldo(),"Horas Trabajadas",getHoras());
     
  }//fin del metodo string
   
}

La clase EmpleadoPorComision extiende a la clase Empleado. Esta clase incluye a un constructor que recibe como argumentos un primer nombre, un apellido, un número de seguro social, un monto de ventas y una tarifa de comisión; los métodos set, para asignar nuevos valores a las variables de instancia TarifaComision y VentasBrutas, respectivamente; métodos get, que obtienen los valores de estas variables de instancia; el método Ingresos para calcular los ingresos de un EmpleadoPorComision; y el método toString que devuelve el tipo del empleado; “empleado por comisión: ”, e información específica del empleado. El constructor también pasa el primer nombre, el apellido y el número de seguro social al constructor de Empleado para inicializar las variables de instancia private de Empleado. El método toString llama al método toString de la superclase  para obtener la información específica del Empleado (es decir, primer nombre, apellido paterno y número de seguro social).



package empleado;

public class EmpleadoPorComision extends Empleado{
   private double VentasBrutas;//ventas totales por totales
   private double TarifaComision;//porcentaje de comision
  
   //constructor con 5 argumentos
  
   public EmpleadoPorComision(String Nombre,String Apellido,String Nss,double Ventas,double Tarifa)
   {
       super(Nombre,Apellido,Nss);
       setVentasBrutas(Ventas);
       setTarifaComision(Tarifa);
      
   }//final del constructor
   //establecer tarifa de comision
  
   public void setTarifaComision(double Tarifa)
   {
       if (Tarifa > 0.0 && Tarifa < 1.0)
      TarifaComision = Tarifa;
       else
           throw new IllegalArgumentException ("la tarifa comsion debe ser mayor a 0.0 o menor a 0.0" );
   }
   // devulve la tarifa comision
  
   public double getTarifaComision()
   {
       return TarifaComision;
   }
   public void setVentasBrutas(double Ventas)
   {
       if (Ventas>= 0.0)
           VentasBrutas = Ventas;
       else
           throw new IllegalArgumentException ("Las ventas brutas deben ser mayores o iguales a 0.0");
   }
   public double getVentasBrutas()
   {
       return VentasBrutas;
   }
   //calcula los ingresos; sobrescribe el método abstracto ingresos en Empleado
  @Override
   public double Ingresos()
   {
       return getTarifaComision() * getVentasBrutas();
   }// fin del metodo ingresos
   // devuelve representación String de un objeto EmpleadoPorComision
   @Override
   public String toString()
   {
       return String.format("%s: %s\n%s: $%,.2f; %s: %.2f","empleado por comisión",super.toString (),"ventas brutas" ,getVentasBrutas(),"tarifa de comisión" ,getTarifaComision() );
   }
  
   }


La clase EmpleadoBaseMasComision extiende a la clase EmpleadoPorComision y, por lo tanto, es una subclase indirecta de la clase Empleado. La clase EmpleadoBaseMasComision tiene un constructor que recibe como argumentos un primer nombre, un apellido paterno, un número de seguro social, un monto de ventas, una tarifa de comisión y un salario base. Después pasa todos estos parámetros, excepto el salario base, al constructor de EmpleadoPorComision para inicializar los miembros heredados. EmpleadoBaseMasComision también contiene un método establecer (set) para asignar un nuevo valor a la variable de instancia salarioBase y un método obtener (get) para devolver el valor de salarioBase . El método ingresos calcula los ingresos de un EmpleadoBaseMasComision. Observe que el método ingresos llama al método ingresos de la superclase EmpleadoPorComision para calcular la porción con base en la comisión de los ingresos del empleado; éste es otro buen ejemplo de reutilización de código. El método toString de EmpleadoBaseMasComision crea una representación String de un EmpleadoBaseMasComision , la cual contiene “ con salario base", seguida del objeto String que se obtiene al invocar el método toString de la superclase EmpleadoPorComision (otro buen ejemplo de reutilización de código), y después el salario base. El resultado es un objeto String que empieza con “con SalarioBaseEmpleadoPorComisión”, seguido del resto dé la información de EmpleadoBaseMasComision. Recuerde que el método toString de EmpleadoPorComision obtiene el primer nombre, el apellido paterno y el número de seguro social del empleado mediante la invocación al método toString de su superclase (es decir, Empleado); otro ejemplo más de reutilización de código. El método toString de EmpleadoBaseMasComision inicia una cadena de llamadas a métodos que abarcan los tres niveles de la jerarquía de Empleado.






package empleado;

public class EmpleadoBaseMasComision extends EmpleadoPorComision
{
    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)
    {
        super(Nombre,Apellido,Nss,Ventas,Tarifa);
        setSalarioBase(Salario);
    }//fin del costructor
  
    //establecer salario base
    public void setSalarioBase(double Salario)
    {
        if (Salario >= 0.0)
        SalarioBase = Salario;
        else
        throw new IllegalArgumentException("El salario base debe der mayor o igual que 0.0 ");
    }
    // devuelva salario minimo
    public double getSalarioBase()
    {
        return SalarioBase;
    }
    // calcula los ingresos; sobrescribe el método ingresos en EmpleadoPorComision
    @Override
    public double Ingresos()
    {
        return getSalarioBase() + super.Ingresos();
    }//fin del metodo
    // devuelve representación String de un objeto EmpleadoBaseMasComision
    @Override
    public String toString()
    {
    return String.format("%s %s; %s: $%,.2f","con salario base",super.toString(),"salario base",getSalarioBase());         
    }
   
}


El procesamiento polimórfico, el operador instanceof  y la conversión descendente

Para probar nuestra jerarquía de Empleado, la aplicación a continuación crea un objeto de cada una de las cuatro clases concretas EmpleadoAsalariado, EmpleadoPorHoras, EmpleadoPorComision y EmpleadoBaseMasComision. El programa manipula estos objetos, primero mediante variables del mismo tipo de cada objeto y después mediante el polimorfismo, utilizando un arreglo de variables Empleado.


Al procesar los objetos mediante el polimorfismo, el programa incrementa el salario base de cada EmpleadoBaseMasComision en un 10% ; para esto se requiere determinar el tipo del objeto en tiempo de ejecución. Por último, el programa determina e imprime en forma polimórfica el tipo de cada objeto en el arreglo Empleado.Se crean objetos de cada una de las cuatro subclases concretas de Empleado. Se imprimen en pantalla la representación String y los ingresos de cada uno de estos objetos sin usar el polimorfismo. El método prrintf  llama en forma implícita al método toString de cada objeto, cuando éste se imprime en pantalla como un objeto String con el especificador de formato %s.



package empleado;

public class PruebaSistemaNomina
{
public static void main (String[] args)
{
    EmpleadoAsalariado empleadoAsalariado = new EmpleadoAsalariado("Juan","Sanchez","111-11-1111",800.00);
    EmpleadoPorHoras empleadoPorHoras = new EmpleadoPorHoras("Karina","Garcia","222-22-2222",16.75,40);
    EmpleadoPorComision empleadPorComision = new EmpleadoPorComision("Susana","Martinez","333-33-3333",10000,0.06);
    EmpleadoBaseMasComision empleadoBaseMasComision = new EmpleadoBaseMasComision("Roberto","Gasca","444-44-4444",5000,0.04,300);

    System.out.println(" Empleados procesados por separado:\n");
 
  System.out.printf("%s\n%s: $%,.2f\n \n ",empleadoAsalariado, "ingresos",empleadoAsalariado.Ingresos());
  System.out.printf("%s\n%s: $%,.2f\n \n ",empleadoPorHoras, "ingresos", empleadoPorHoras.Ingresos());
  System.out.printf("%s\n%s: $%,.2f\n \n ",empleadPorComision, "ingresos",empleadPorComision.Ingresos());
  System.out.printf("%s\n%s: $%,.2f\n \n ",empleadoBaseMasComision,"ingresos",empleadoBaseMasComision.Ingresos());
  // crea un arreglo Empleado de cuatro elementos
 
  Empleado[] empleados = new Empleado[4];
  // inicializa el arreglo con objetos Empleado
  empleados[0] = empleadoAsalariado;
  empleados[1] = empleadoPorHoras;
  empleados[2] = empleadPorComision;
  empleados[3] = empleadoBaseMasComision;
 
  System.out.println("Empleados procesados en forma polimorfica :\n");
  // procesa en forma genérica a cada elemento en el arreglo de empleados
 
  for (Empleado EmpleadoActual : empleados )
  {
    System.out.println(EmpleadoActual); // invoca a toString
    // determina si el elemento es un EmpleadoBaseMasComision
   
    if(EmpleadoActual instanceof EmpleadoBaseMasComision)
    {
       // conversión descendente de la referencia de Empleado
       // a una referencia de EmpleadoBaseMasComision
       EmpleadoBaseMasComision empleado = (EmpleadoBaseMasComision) EmpleadoActual;
       empleado.setSalarioBase(1.10*empleado.getSalarioBase());
      
       System.out.printf(" el nuevo salario base con 10%% de aumento es : $%,.2f\n",empleado.getSalarioBase());
      
    }
     
  }
 
}
}

http://www.sc.ehu.es/sbweb/fisica/cursoJava/fundamentos/clases1/string.htm
Ditel 9na. edicion pag. 258, Sobrecarga de metodos
Ditel 9na. edicion pag. 242, Metodo static
Ditel 9na. edicion pag. 348, 403 Sobrecarga de constructores
http://www.sc.ehu.es/sbweb/fisica/cursoJava/fundamentos/colecciones/stringtokenizer.htm
http://www.w3ii.com/es/java_util/default.html
http://www.w3ii.com/default.html
https://users.dcc.uchile.cl/~lmateu/Java/Apuntes/tiposprim.htm
http://labojava.blogspot.mx/2012/05/casteos.html
http://www.sc.ehu.es/sbweb/fisica/cursoJava/fundamentos/estatico/math/math.htm
http://www.sc.ehu.es/sbweb/fisica/cursoJava/Intro.htm
https://www.solvetic.com/tutoriales/article/974-java-palabra-reservada-super/
http://www.binarykode.com/bdescargas/Manuales%20y%20Documentos/JAVA/Interfaces%20de%20Usuario/Tutorial%20JAVA%20avanzado%20(I)/string/accessors.html
https://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=653:ejemplo-de-herencia-en-java-uso-de-palabras-clave-extends-y-super-constructores-con-herencia-cu00686b&catid=68&Itemid=188