Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 72

INSTITUTO DE EDUCACION

SUPERIOR “ISABEL LA
CATOLICA”

DESA
RRO
LLO

MÓDULO
INFORMATIVO
2020

DOCENTE
MANUEL TRUJILLO F.
CONTENIDO
CAPITULO I: LENGUAJE DE PROGRAMACIÓN JAVA NETBEANS Y LAS
DIFERENTES ESTRUCTURAS DE PROGRAMACIÓN LINEALES................................3
1. CONSTANTES...............................................................................................................4
1.1. Constantes literales.................................................................................................4
1.2. Constantes declaradas............................................................................................4
1.3. Constantes expresión..............................................................................................5
2. VARIABLES..................................................................................................................5
2.1. Declaración de variables........................................................................................5
2.2. Iniciación de variables............................................................................................5
2.3. Utilización de variables..........................................................................................6
2.4. Diferencias entre ambas.........................................................................................6
3. ESTRUCTURAS SECUENCIALES DE PROGRAMACIÓN...................................7
4. ESTRUCTURAS CONDICIONALES SIMPLES Y DOBLES...................................8
4.1. Simples:...................................................................................................................8
4.2. Dobles:.....................................................................................................................9
5. ESTRUCTURAS CONDICIONALES ANIDADAS Y MÚLTIPLES........................9
5.1. Condicionales anidadas:.........................................................................................9
5.2. Condiciones múltiples:.........................................................................................10
6. ESTRUCTURAS REPETITIVAS O BUCLES..........................................................10
6.1. La estructura repetitiva for.................................................................................11
6.2. LA ESTRUCTURA REPETITIVA WHILE......................................................13
6.3. LA ESTRUCTURA REPETITIVA DO - WHILE.............................................15
CAPITULO II: ARREGLOS O ARRAYS Y SUS DISTINTOS MÉTODOS EN JAVA
NETBEANS..............................................................................................................................17
1. Array o arreglo unidimensional..................................................................................17
1.1. Inicializando un array unidimensional en Java..................................................17
1.2. Asignación de valores en un array unidimensional en Java..............................18
2. Array (arreglo) multidimensional en Java.................................................................21
2.1. Inicializar un array multidimensional en Java...................................................21
2.2. Llenado de un array multidimensional en Java.................................................22
2.3. Longitud de un array...........................................................................................24
2.4. La clase Arrays.....................................................................................................24
3. MÉTODOS DE ORDENAMIENTO EN ARREGLOS.............................................26
3.1. Método de la burbuja...........................................................................................26
3.2. Método por selección:...........................................................................................27

2
3.3. Método por inserción:..........................................................................................29
4. MÉTODOS DE BÚSQUEDA EN ARREGLOS.........................................................31
4.1. Búsqueda binaria..................................................................................................31
4.2. Búsqueda secuencial.............................................................................................33
CAPITULO III: PROGRAMACION ORIENTADA A OBJETOS EN JAVA...................35
1. Clases.............................................................................................................................36
2. OBJETOS.....................................................................................................................37
3. OTROS CONCEPTOS DE LA PROGRAMACION ORIENTADA A OBJETOS.40
3.1. Constructores y destructores...............................................................................40
3.1.1. Constructor.......................................................................................................41
3.1.2. Destructor..........................................................................................................42
3.2. Encapsulación.......................................................................................................49
3.3. Herencia................................................................................................................51
3.4. Polimorfismo.........................................................................................................64

3
CAPITULO I: LENGUAJE DE PROGRAMACIÓN JAVA
NETBEANS Y LAS DIFERENTES ESTRUCTURAS DE
PROGRAMACIÓN LINEALES

1. CONSTANTES

Una constante es un dato cuyo valor no puede cambiar durante la ejecución del
programa. Recibe un valor en el momento de la compilación y este permanece
inalterado durante todo el programa.

En el siguiente ejemplo se contemplan varios casos:

Min = 0;

Max = 100;

Sep = 10;

En este ejemplo se declaran tres constantes (Min, Max y Sep).

Se puede hacer una división de las constantes en tres clases:

1.1. Constantes literales

Son valores de cualquier tipo que se utilizan directamente, no se declaran ya que


no tienen nombre. En el siguiente ejemplo tienes un par de constantes literales
(el 3, el 4, y el 3.1416):

VolumenEsfera := 4/3 * 3.1416 * Radio * Radio * Radio;

1.2. Constantes declaradas

También llamadas constantes con nombre, son las que se declaran asignándoles
un valor directamente. Por ejemplo:

Pi = 3.141592; (* valor real *)

4
Min = 0; (* entero *)

Max = 99; (* entero *)

Saludo = 'Hola'; (* cadena caract. *)

1.3. Constantes expresión

También se declaran, pero a estas no se les asigna un valor directamente, sino


que se les asigna una expresión. Esta expresión se evalúa en tiempo de
compilación y el resultado se le asigna a la constante. Ejemplo:

Min = 0;
Max = 100;
Intervalo = 10;
N = (Max - Min) / Intervalo;

2. VARIABLES

Una variable es un nombre asociado a un elemento de datos que está situado en


posiciones contiguas de la memoria principal, y su valor puede cambiar durante la
ejecución de un programa.

Toda variable pertenece a un tipo de dato concreto. En la declaración de una


variable se debe indicar el tipo al que pertenece. Así tendremos variables enteras,
reales, booleanas, etc. Por otro lado, distinguimos tres partes fundamentales en la
vida de una variable:

2.1. Declaración de variables

Esta es la primera fase en la vida de cualquier variable. Acá se asigna el tipo de


dato que tendrá la variable como: enteras, reales, booleanas, etc.

2.2. Iniciación de variables

5
Esto no es más que darle un valor inicial a una variable. Así como lo primero
que se hace con una variable es declararla, lo siguiente tiene que ser iniciarla.
Esto se hace para evitar posibles errores en tiempo de ejecución, pues una
variable tiene un valor indeterminado después de declararla.

Veamos un ejemplo que reúne los dos casos:

I =1;
readln(n);
while i < n do begin
(* cuerpo del bucle *)
i=i+1

2.3. Utilización de variables

Una vez declarada e iniciada una variable, es el momento de utilizarla. Esta es


la parte que presenta un mayor abanico de posibilidades. A continuación, tienes
unas cuantas:

Incrementar su valor:
i=i+1
Controlar un bucle:
for i=1 to 10 do ...
Chequear una condición:
if i<10 then ...
Participar en una expresión:
n = (Max - Min) div i

2.4. Diferencias entre ambas

Después de haber visto cada una por separado, pasemos a explicar las
diferencias que existen entre constantes y variables. A primera vista pudieran
parecer conceptos similares, pero realmente son cosas muy distintas. Y esta

6
distinción viene dada por la posibilidad que tienen las variables para cambiar de
valor.

Principales diferencias:

 Las constantes ya reciben un valor inicial en su declaración


 Las variables primero se declaran, luego se inician, y luego se usan
 Las constantes, una vez declaradas mantienen su valor durante toda la
ejecución del programa
 En cambio, las variables pueden cambiar su valor tantas veces como deseen
 Además de cambiar su valor, las variables también pueden cambiar de
tamaño en tiempo de ejecución (punteros)

3. ESTRUCTURAS SECUENCIALES DE PROGRAMACIÓN


El orden en que se ejecutan por defecto las sentencias de un programa es
secuencial. Esto significa que las sentencias se ejecutan en secuencia, una después
de otra, en el orden en que aparecen escritas dentro del programa.
La estructura secuencial está formada por una sucesión de instrucciones que se
ejecutan en orden una a continuación de la otra.
Cada una de las instrucciones están separadas por el carácter punto y coma (;).
Las instrucciones se suelen agrupar en bloques.
El bloque de sentencias se define por el carácter llave de apertura ({) para marcar el
inicio del mismo, y el carácter llave de cierre (}) para marcar el final.
Ejemplo:
{
instrucción 1;
instrucción 2;
instrucción 3;
}

En Java si el bloque de sentencias está constituido por una única sentencia no es


obligatorio el uso de las llaves de apertura y cierre ({ }), aunque sí recomendable.

Ejemplo de programa Java con estructura secuencial: Programa que lee dos
números por teclado y los muestra por pantalla.

7
/* Programa que lea dos números por teclado y los muestre por
pantalla.
*/
import java.util.*;
public class Main {
public static void main(String[] args){
//declaración de variables
int n1, n2;
Scanner sc = new Scanner(System.in);
//leer el primer número
System.out.println("Introduce un número entero: ");
n1 = sc.nextInt(); //lee un entero por teclado
//leer el segundo número
System.out.println("Introduce otro número entero: ");
n2 = sc.nextInt(); //lee un entero por teclado

//mostrar resultado
System.out.println("Ha introducido los números: " + n1 + " y " +
n2);
}
}

4. ESTRUCTURAS CONDICIONALES SIMPLES Y DOBLES


Las estructuras condicionales comparan una variable contra otro(s) valor(es), para
que, en base al resultado de esta comparación, se siga un curso de acción dentro del
programa. Cabe mencionar que la comparación se puede hacer contra otra variable
o contra una constante, según se necesite.

4.1. Simples:
La estructura condicional más simple en Java es el if, se evalúa una condición y
en caso de que se cumpla se ejecuta el contenido entre las llaves {} o en caso de
que se omitan se ejecuta el código hasta el primer «;» por lo tanto si no se usan
los {} la condición aplica solo a la siguiente instrucción al if.

If (condicion) {
ejecutar();
}

// Los {} son opcionales

8
if (condicion)
ejecutar();

// Y mas compacto
if (condicion) ejecutar();

Por lo tanto, el uso de las llaves es opcional cuando dentro de la condición hay
una sola línea de código, pero puede generar errores si se añade más código que
se espere que se ejecute bajo la condición si no recordamos que tenemos que
añadir las llaves en estos casos. Personalmente, prefiero usar las llaves y en caso
de no utilizarlas pondría el if completo en una única línea para que sea más claro
que la condición solo aplica a esa línea.

4.2. Dobles:
Con el if solo podemos hacer que se ejecute un fragmento de código o no pero
en el caso de que no se cumpla la condición no se hace nada (sigue el flujo
normal de ejecución) por lo que si queremos que se ejecute otra cosa cuando no
se cumpla la condición solo con el if tenemos que hacer otro con la condición
inversa provocando que se tenga que comprobar la condición 2 veces mientras
que si usamos el else solo necesitamos hacer la comprobación una sola vez.

// Usando if con else


// Si la temperatura es mayor que 25 ... y si no ...
if (temperatura > 25) {
System.out.println("A la playa!!!");
} else {
System.out.println("Esperando al buen tiempo...");
}

5. ESTRUCTURAS CONDICIONALES ANIDADAS Y MÚLTIPLES


5.1. Condicionales anidadas:
Es posible anidar ifs para reorganizar las condiciones o hacerlas más sencillas
lo que en muchas ocasiones hace el código más fácil de leer, a continuación,
una de las posibles formas posibles.

if (temperatura > 15) {


if (temperatura > 25) {
// Si la temperatura es mayor que 25 ...

9
System.out.println("A la playa!!!");
} else {
System.out.println("A la montaña!!!");
}
} else if (temperatura < 5) {
if (nevando) {
System.out.println("A esquiar!!!");
}
} else {
System.out.println("A descansar... zZz");
}

5.2. Condiciones múltiples:

Con el switch se puede hacer un control del tipo if else if… más estructurado,
pero en realidad no exactamente igual puesto que con el switch lo que se hace es
definir un conjunto de casos que van a tener una ejecución distinta y se ejecutará
el caso que coincida con el valor indicado en el switch.

switch (variable) {
case valor_1:
case valor_2:
// Ejecutar si el valor de variable es igual a valor_1 o a valor_2
ejecutarA();
break; // Salir del switch
case valor_3:
// Ejecutar si el valor de variable es igual a valor_3
ejecutarB();
break; // Salir del switch
default:
// Ejecutar si el valor de varible es distinto del del resto de
casos
ejecutarC();
break; // Salir del switch
}

10
6. ESTRUCTURAS REPETITIVAS O BUCLES
Esta vez vamos a ver cómo se utiliza las estructuras de control repetitivas en Java
(también conocidas como ciclos o bucles). Como mencionaba en el tutorial
Estructuras de control condicionales vamos a necesitar de estas estructuras al
momento de programar, y pues bueno este tipo de estructuras de control se las
utiliza cuando necesitamos recorrer un conjunto de datos, por ejemplo, al leer un
archivo, al leer registros de una base de datos, en fin, en todos los problemas en los
que se tenga que hacer iteraciones, bucles, siempre vamos a necesitar de estas
estructuras.

6.1. La estructura repetitiva for


El ciclo for permite ejecutar un conjunto de sentencias un número fijo de veces y
antes de saber cómo funciona esta sentencia, primero que nada, vamos a ver la
sintaxis.

Nota importante: Este ciclo se lo utiliza cuando sabemos el número de veces


que se debe ejecutar el ciclo.

for(variable_inicializacion;condicion;incremento)
{
//instrucciones
}

6.1.1. Vamos a ver cómo funciona


Como podemos ver esta sentencia está compuesta de 3 partes separadas
por; (punto y coma) la primera parte llamada inicialización permite
controlar el ciclo, suele ser la variable de tipo entero por lo general la letra
i, pero puede ser cualquier otra letra, esta variable es declarada e
inicializada dentro de la estructura, aunque se la puede hacer desde fuera,
la variable de inicialización indica desde que valor va empezar el ciclo.

La segunda parte es la condición, la condición indica cuantas veces se va


ejecutar el ciclo y se evalúa antes de cada iteración, si la condición es
verdadera el ciclo continúa, tomar en cuenta que, si se omite esta parte, el
ciclo se vuelve infinito.

11
La tercera parte es el incremento o decremento y le indica en pasos de
cuanto debe incrementarse o decrementarse la variable de inicialización en
cada iteración, por lo general es de uno en uno, pero todo dependerá del
problema que se quiera resolver, también puede omitirse esta parte, si se lo
hace el ciclo se vuelve infinito (no siempre).

Ahora un ejemplo
Imprimir por consola los números enteros desde el 2 hasta 20
Este es un problema sencillo que se lo puede resolver utilizando el ciclo
for:

public class TestCiclos {


public static void main(String[] args) {
for (int i = 2; i < 21; i += 2) {
System.out.println("Número: " + i);
}
}
}

6.1.2. Proceso
La variable i es declarada en inicializada en 2 (también se la puede
declarar en inicializar fuera y omitir esa parte).
Seguido de esto el compilador verifica si la variable i es menor a 21, si es
correcto continúa el ciclo, ejecuta la (s) instrucciones y luego.
La variable i se incrementa en 2.
El compilador repite las mismas instrucciones desde el paso 2 hasta que i
toma el valor de 22, la condición se verifica y como no se cumple, el ciclo
termina.
El ciclo for puede tomar varias sintaxis sin que esto genere errores de
compilación o cambie el resultado del programa. A continuación, se
muestra algunas sintaxis con las que nos podemos encontrar.
Ahora el mismo ejemplo anterior lo adaptamos a esta sintaxis, como se
puede ver la variable de incremento se omite y se la pone dentro del ciclo,
luego de las instrucciones.

12
public class TestCiclos {
public static void main(String[] args) {
for (int i = 2; i < 21;) {
System.out.println("Número: " + i);
i += 2;
}
}
}

Nota: En este caso la variable i es visible sólo dentro del ciclo for, puesto
que se la ha declarado e inicializado dentro del ciclo, si la quisiéramos
utilizar fuera, nos va lanzar un error.

En algunos casos también se presenta con la siguiente sintaxis, en este


caso la variable de inicio está fuera del ciclo y la variable de incremento
está después de las instrucciones a ejecutar.

public class TestCiclos {


public static void main(String[] args) {
int i = 2;
for (; i < 21;) {
System.out.println("Número: " + i);
i += 2;
}
}
}

En este caso la variable i es visible para todo el programa puesto que la


hemos declarado fuera del ciclo.

6.2. LA ESTRUCTURA REPETITIVA WHILE


Esta estructura es parecida al ciclo for, la diferencia está en su sintaxis:

while (condicion) {
//instrucciones
}

El ciclo while permite ejecutar n veces un conjunto de instrucciones siempre y


cuando la condición se cumpla o sea verdadera.

13
Nota importante: Este ciclo se utiliza cuando no sabemos el número de veces
exacto que se ejecutará el ciclo.
Si la condición siempre es verdadera o siempre se cumple este ciclo puede crear
un bucle que nunca termine, por eso hay que tener en cuenta que en algún
momento del ciclo la condición no debe cumplirse (debe volverse falsa) para que
el ciclo termine, caso contrario el ciclo se vuelve infinito.

Vamos a ver un ejemplo


Ingresar un número por teclado e imprimir por la consola su decena superior:
Ejemplo sin ingreso el número 5, su decena superior es 10, si ingreso el 25, su
decena superior es 30.

Análisis del problema para saber que ciclo utilizar


El ejemplo anterior lo podemos resolver también con un ciclo for, pero como no
sabemos cuántas iteraciones o cuantas veces se repite el ciclo ya que la decena
superior cambiará de acuerdo al número ingresado, es recomendable utilizar el
ciclo while.

A continuación, el código.

import java.util.Scanner;

public class TestCiclos {


public static void main(String[] args) {
int numero;
Scanner entrada = new Scanner(System.in);
System.out.println("Ingrese un número:");

try {
numero = entrada.nextInt();
while ((numero % 10) != 0) {
numero++;
}
System.out.println("La decena superior es: " +
numero);
} catch (Exception e) {
System.out.println("Número no válido");

14
}
}
}

Explicando un poco el ciclo, se obtiene el número desde teclado (si deseas un


ejemplo completo de cómo ingresar números desde teclado puedes ingresar a
esta entrada Entrada de datos en Java utilizando la Clase Scanner), en la línea 13
empieza el ciclo while, la condición para que ingrese al ciclo, es que el módulo o
resto de dividir el número entre 10 sea diferente de cero.
El módulo de dividir cualquier número entre 10, (excepto los múltiplos de 10
por ejemplo 10, 20, 30, 40, etc..) siempre nos dará un valor diferente de cero y
por ende ingresa al ciclo.
Entonces la idea es ir incrementando el número ingresado hasta que sea múltiplo
de 10 y con esto el módulo de dividir el número entre 10 va ser cero y por ende
ya no va ingresar al bucle.
Con esto el número se habrá incrementado y sabremos cual es la decena superior
de cualquier número ingresado.

6.3. LA ESTRUCTURA REPETITIVA DO - WHILE


El ciclo do while también permite ejecutar n número de veces un conjunto de
instrucciones, es muy parecida a las otras 2 estructuras de control que hemos
visto anteriormente, salvo que este ciclo siempre se ejecuta por lo menos una
vez, recordemos que en el ciclo for debemos conocer el número de veces que se
va ejecutar las instrucciones, el ciclo while hay una condición que se debe
cumplir para que se ejecuten las instrucciones, en cambio en el ciclo do while
primero se ejecutan las instrucciones y luego verifica la condición y si esta es
verdadera el ciclo se repite hasta verificar de nuevo la condición, para salir del
ciclo la condición se debe volver falsa.

La sintaxis del ciclo do while es la siguiente:

do {
//instrucciones
} while (condicion);

Vamos a ver un ejemplo

15
Obtener los dígitos de un número ingresado por teclado, ejemplo 100, tiene 3
dígitos.
Una forma para obtener los dígitos que tiene un número, realizamos divisiones
sucesivas entre 10 hasta que el número se vuelve cero (del resultado de la
división sólo se debe tomar la parte entera), para obtener el número de dígitos
contamos las veces que se ha dividido. Por ejemplo, tenemos el número 345:
El resultado debe ser almacenado en una variable de tipo entero.

345/10=34

34/10=3

3/10=0

En este caso se ha realizado 3 divisiones por lo que el número de dígitos es 3.

public class TestCiclos {

public static void main(String[] args) {


int numero = 345;
int contador = 0;
do {
numero /= 10;
System.out.println(numero);
contador++;
} while (numero != 0);
System.out.println("El número tiene " + contador + " dígitos");
}
}

También hubiésemos podido utilizar el ciclo while que funciona con todos los
números, menos con el número 0 (cero), no entra en el ciclo porque número es
igual que cero y por ende la respuesta va ser:

"El número tiene 0 dígitos"

16
Esto se soluciona con el ciclo do while que me garantiza que por lo menos el ciclo
se va ejecutar una vez, con esto, si se ingresa el número cero va ingresar al ciclo ya
que la condición se verifica al final.
Nota importante: Este ciclo se utiliza cuando sabemos que se ejecutará el ciclo al
menos una vez.

CAPITULO II: ARREGLOS O ARRAYS Y SUS DISTINTOS


MÉTODOS EN JAVA NETBEANS
Los arrays o arreglos en Java, agrupan valores del mismo tipo guardados en una misma
variable y se puede acceder de manera independiente.

Estos Arrays pueden ser unidimensionales o multidimensionales, usar estos tipos de


arrays son muy beneficios para almacenar varios valores en una sola variable, ademas
su uso en Java es muy sencilla

1. Array o arreglo unidimensional

Un array (o arreglo) unidimensional solo presenta una sola fila, también otros la
llaman vectores de una dimensión.

Existen múltiples maneras de aplicar estos arrays en Java, por ejemplo, si queremos
guardar las calificaciones de un conjunto alumnos podríamos utilizar un array
unidimensional para generar sus notas de aprobación, etc.

Sintaxis

tipo nombre[];

Cuando declaramos un array unidimensional y queremos recorrer este array para


obtener un valor guardado debemos recorrer desde la posición 0 hasta la posición n-
1 donde n es igual al tamaño de nuestro array en Java.

17
1.1. Inicializando un array unidimensional en Java

Estos arrays de Java de una dimensión lo instanciamos usando el operador new


para crear la instancia del array, si queremos también podemos indicar el
tamaño en la misma linea.

int calificaciones[]; //también puede ser valido int[] calificaciones;


calificaciones = new int[10]; // Es el tamaño del array
//Otra forma es declararlo todo a la vez
//int calificaciones[]=new int[10]

Los arrays unidimensionales se pueden inicializar las veces que queramos, pero
debemos tomar en cuenta que cuando hacemos esto perdemos todo el
contenido del array guardado.

int notas[]=new notas[42];


...
notas=new notas[31];

1.2. Asignación de valores en un array unidimensional en Java

Asignar un valor al array se la puede hacer directamente cuando declaramos el


array y asignarle un valor o declararlo posteriormente y lo podemos llenar con
los valores que sean necesarios.

calificaciones[2]=71;
int calificaciones[] = {33, 21, 71};
int calificaciones[]= new int[] {33,21,71};

Gracias a las estructuras de control repetitivas while, do while o for de Java


podemos rellenar y obtener fácilmente los valores de un array unidimensional.

18
Estos arrays unidimensionales también pueden ser igualados a otro array para
que tenga los mismos valores, pero deben cumplir la condición que sean del
mismo tipo.

int notas[];
int ejemplo[]=new int[10];
notas=ejemplo;
Ejemplo de un array (arreglo) unidimensional en Java
import java.util.Scanner;
/**
*
* @author Creatividad Codificada
*/
public class ArrayUnidimensional
{
public static void main(String[] args)
{
Scanner t = new Scanner (System.in);
int dim;
int notas[];
System.out.print("DIGITE LA DIMENSION DEL ARRAY NOTAS: ");
dim=t.nextInt();
notas = new int [dim];
System.out.println("INTRODUZCA LOS VALORES DEL ARRAY");
for (int k=0;k<dim;k++)
{
System.out.print("notas [ "+ k + "] = ");
notas[k]=t.nextInt();
}
// Ordenamos el array

19
int aux;
for (int i=0;i<dim;i++)
for (int j=0;j<dim-1;j++)
{
if (notas[j]>notas[j+1])
{
aux = notas[j];
notas[j]=notas[j+1];
notas[j+1]=aux;
}
}

/* Arrays.sort(notas) tambien ordena el array


de forma ascendente, se debe usar import java.util.Arrays;
*/
//Imprime en consola el array ordenado
System.out.println("ARRAY ORDENADO");
for (int k=0;k<dim;k++)
System.out.println("notas [ " +k+ " ] = "+notas[k]);
}
}
Resultado

DIGITE LA DIMESION DEL ARRAY NOTAS: 7

INTRODUZCA LOS VALORES DEL ARRAY

notas [ 0] = 78

notas [ 1] = 71

notas [ 2] = 88

notas [ 3] = 65

20
notas [ 4] = 45

notas [ 5] = 51

notas [ 6] = 16

ARRAY ORDENADO

notas [ 0 ] = 16

notas [ 1 ] = 45

notas [ 2 ] = 51

notas [ 3 ] = 65

notas [ 4 ] = 71

notas [ 5 ] = 78

notas [ 6 ] = 88

2. Array (arreglo) multidimensional en Java

Estos arrays manejan dos o más dimensiones, esto quiere decir que puede haber un
array que contenga otro array.

Para entender mejor imagínense un cubo de Ruby donde cada cuadradito guardara
un valor del array o arreglo y si hablamos de tamaño un cubo Ruby sería un array
de 3x3x3.

21
Sintaxis

int notas[][];
2.1. Inicializar un array multidimensional en Java

En los arrays multidimensionales también usan la instrucción “new” para hacer


una nueva instancia de la clase Arrays de Java.

notas = new int[3][12];

También podemos iniciar nuestro array multidimensional en Java


creativamente.

int notas[][]=new int[5][]; // Asignamos un tamaño al primer array y el


// array faltante se la puede asignar después
notas[0]=new int[7]; // Array en la posición 0 tendrá 7 enteros
notas[1]=new int[17]; // Array en la posición 1 tendrá 17 enteros
notas[2]=new int[44]; // Array en la posición 2 tendrá 44 enteros
notas[3]=new int[8]; // Array en la posición 3 tendrá 8 enteros
notas[4]=new int[57]; // Array en la posición 4 tendrá 57 enteros

2.2. Llenado de un array multidimensional en Java

Los arrays en Java pueden guardar valores de forma directa y se la hace


similar a los unidimensionales, solo se separa mediante llaves y comas.

int notas [][] = {{8,18,21},{15,17,11},{0,1,18}};


Generalmente para llenar y recuperar los valores de una matriz o arreglo en
Java hacemos uso de las estructuras de control repetitivas o iterativas while,
do while o for.

Ejemplo de array multidimensional en Java


import java.util.Scanner;
public class ArrayMultidimensional {

22
public static void main(String[] args) {
Scanner en = new Scanner (System.in);
byte dim = 3; // DIMENSION DE LA MATRIZ
int aux = 0;
int matriz[][] = new int [dim][dim];
System.out.println("SUMA DE LA DIAGONAL PARA UNA MATRIZ
CUADRADA");
System.out.println("TECLEE LOS NÚMEROS DE LA MATRIZ");
for(int i=0 ; i<matriz.length ; i++)
{
for(int j=0; j<matriz.length; j++)
{
System.out.print("matriz["+i+"]"+"["+j+"] = ");
matriz[i][j]=en.nextInt();
}
}
for(int k=0 ; k<matriz.length ; k++)
{
for(int l=0; l<matriz.length; l++)
{
if (k==l)
{
aux = aux + matriz[k][l];
System.out.print(matriz[k][l] + "\t");
}
else System.out.print(matriz[k][l] + "\t");
}
System.out.println();
}
System.out.println("LA SUMA DE LA DIAGONAL ES: "+aux);

23
}
}

Resultado
SUMA DE LA DIAGONAL PARA UNA MATRIZ CUADRADA
TECLEE LOS NÚMEROS DE LA MATRIZ
matriz[0][0] = 15
matriz[0][1] = 48
matriz[0][2] = 75
matriz[1][0] = 65
matriz[1][1] = 85
matriz[1][2] = 24
matriz[2][0] = 35
matriz[2][1] = 46
matriz[2][2] = 67
15 48 75
65 85 24
35 46 67
LA SUMA DE LA DIAGONAL ES: 167

2.3. Longitud de un array

El método length nos da la posibilidad de obtener la longitud del array


unidimensional o multidimensional.

notas.length // tamaño del array


notas[2].length // tamaño del elemento

2.4. La clase Arrays

24
Esta clase estática es muy útil cuando necesitamos obtener o realizar algunas
operaciones específicas, si la deseamos usar se ubica dentro el paquete
conocido como java.utils.

Existen muchos métodos útiles para nuestros programas, ya que su


implementación es muy sencilla, a continuación, se detallarán algunas.

1) Método fill

El método fill nos permite llenar todo el array, pero de una dimensión con
algún valor que le indiquemos, el array debe estar seguido del valor que
deseamos rellenar en todo el array, esto lo declaramos en los argumentos del
método fill.

int notas[]=new int[10];


Arrays.fill(notas, 9); //Se llena todo el array con 9
También se puede definir desde que índice hasta que índice queremos
rellenar y con qué valor

Arrays.fill(notas,0,2,51);//Del elemento 0 al 2 sus valores


cambiaran a 51

2) Método equals

El método equals de Java compara dos arrays o arreglos, este método nos
devuelve “true” si son exactamente iguales los dos arrays, es decir deben
tener el mismo tipo de dato, tamaño y sus valores deben ser iguales, en caso
de no ser así nos devolverá falso, con esto simplificamos la forma de
establecer si son iguales dos arrays (arreglos).

Arrays.equals(array1 , array2)

3) Método sort

Nos da la posibilidad de ordenar nuestro array de forma ascendente

int v[]={10,6,7,12,1,4,9,11,8,3};
Arrays.sort(v);//Estará ordenado

25
Arrays.sort(v,2,8);//Ordena del segundo al octavo elemento del
array

4) System.arraysCopy

Este método nos da la posibilidad de copiar un array en otro array, este


método recibe cinco argumentos.

arraycopy(Object ob, int iniPos, Object destino, int destPos, int tamanio)

src – el array principal.


iniPos – Es la posición inicial para copiar del array principal.
destino – el array de destino.
destPos – posición inicial en los datos de destino.
tamanio – Es la cantidad de elementos a copiar.

int array1[]={0,5,8,9,11};
int array2[]={4,8,6,0,1,2,4,7,9,6};
System.arraycopy(array1, 0, array2, 0, array1.length);
for (int i=0;i<=9;i++){
System.out.print(array2[i]+" ");
} //Imprime 0 5 8 9 11 2 4 7 9 6

3. MÉTODOS DE ORDENAMIENTO EN ARREGLOS


3.1. Método de la burbuja

El método de la burbuja es uno de los métodos de ordenación más conocidos y


uno de los primeros que aprenden los programadores.

Consiste en comparar pares de elementos adyacentes en un array y si están


desordenados intercambiarlos hasta que estén todos ordenados.

Si A es el array a ordenar, se realizan A.length-1 pasadas. Si la variable i es la


que cuenta el número de pasadas, en cada pasada i se comprueban los
elementos adyacentes desde el primero hasta A.length-i-1 ya que el resto hasta

26
el final del array están ya ordenados. Si los elementos adyacentes están
desordenados se intercambian.

El método de ordenación de la burbuja en java para ordenar un array A es el


siguiente:

public static void burbuja(int [] A){


int i, j, aux;
for(i=0;i<A.length-1;i++)
for(j=0;j<A.length-i-1;j++)
if(A[j+1]<A[j]){
aux=A[j+1];
A[j+1]=A[j];
A[j]=aux;
}
}
3.2. Método por selección:

Considérese el algoritmo para ordenar un array a[] de enteros en orden


ascendente, es decir, si el array a[] tiene n elementos, se trata de ordenar los
valores del array de modo que a[0] sea el valor más pequeño, el valor
almacenado en a[1] sea el siguiente más pequeño, y así

hasta a[n-1] que ha de contener el elemento de mayor valor. El algoritmo se


apoya en las pasadas que intercambian el elemento más pequeño,
sucesivamente con el elemento de la lista, a[], que ocupa la posición igual al
orden de pasada (hay que considerar el índice 0). La

pasada inicial busca el elemento más pequeño de la lista y se intercambia con


a[0], primer elemento de la lista.

Después de terminar esta primera pasada, el frente de la lista está ordenado y el


resto de la lista a[1], a[2]...a[n-1] permanece desordenado. La siguiente pasada
busca en esta lista desordenada y selecciona el elemento más pequeño, que se
almacena entonces en la posición

27
a[1]. De este modo, los elementos a[0] y a[1] están ordenados y la sublista a[2],
a[3]... a[n-1] desordenado; entonces, se selecciona el elemento más pequeño y
se intercambia con a[2].

El proceso continúa hasta realizar n-1 pasadas, en ese momento la lista


desordenada se reduce a un elemento (el mayor de la lista) y el array completo
queda ordenado. Un ejemplo práctico ayudará a la comprensión del algoritmo.
Consideremos un array a[] con 5 valores enteros 51, 21, 39, 80, 36:

Codificación del algoritmo de selección

El método ordSeleccion() ordena un array de números reales de n elementos, n


coincide con

el atributo length del array. En la pasada i, el proceso de selección explora la


sublista a[i] a

a[n-1] y fija el índice del elemento más pequeño. Después de terminar la


exploración, los elementos

a[i] y a[indiceMenor] se intercambian; operación que se realiza llamando al


método

intercambiar() (es necesario cambiar tipo int por tipo double).

28
/*

ordenar un array de n elementos de tipo double

utilizando el algoritmo de ordenación por selección

*/

public static void ordSeleccion (double a[])


{
int indiceMenor, i, j, n;
n = a.length;
for (i = 0; i < n-1; i++)
{
// comienzo de la exploración en índice i
indiceMenor = i;
// j explora la sublista a[i+1]..a[n-1]
for (j = i+1; j < n; j++)
if (a[j] < a[indiceMenor])
indiceMenor = j;
// sitúa el elemento mas pequeño en a[i]
if (i != indiceMenor)
intercambiar(a, i, indiceMenor);
}
}

3.3. Método por inserción:

El método de ordenación por inserción es similar al proceso típico de ordenar


tarjetas de nombres (cartas de una baraja) por orden alfabético consistente en
insertar un nombre en su posición correcta dentro de una lista que ya está
ordenada. El proceso en el caso de la lista de enteros es:

29
Algoritmo de ordenación por inserción

El algoritmo correspondiente a la ordenación por inserción contempla los


siguientes pasos:

1. El primer elemento a[0] se considera ordenado; es decir, la lista inicial


consta de un

elemento.

2. Se inserta a[1] en la posición correcta; delante o detrás de a[0], dependiendo


de si es

menor o mayor.

3. Por cada bucle o iteración i (desde i=1 hasta n-1) se explora la sublista a[i-1]
...

a[0] buscando la posición correcta de inserción de a[i]; a la vez, se mueven


hacia abajo

(a la derecha en la sublista) una posición todos los elementos mayores que el


elemento a

insertar a[i], para dejar vacía esa posición.

4. Insertar el elemento a[i] a la posición correcta.

Codificación del algoritmo de ordenación por inserción

30
La codificación del algoritmo se realiza en el método ordInsercion(). Se pasa
como argumento

el array, a[], que se va a ordenar de modo creciente; el número de elementos a


ordenar coincide

con el atributo del array length. Los elementos del array son de tipo entero; en
realidad, pueden

ser de cualquier tipo básico y ordinal de Java.

public static void ordInsercion (int [] a)


{
int i, j;
int aux;
for (i = 1; i < a.length; i++)
{
/* indice j es para explorar la sublista a[i-1]..a[0] buscando la
posicion correcta del elemento destino*/
j = i;
aux = a[i];
// se localiza el punto de inserción explorando hacia abajo
while (j > 0 && aux < a[j-1])
{
// desplazar elementos hacia arriba para hacer espacio
a[j] = a[j-1];
j--;
}
a[j] = aux;
}
}

4. MÉTODOS DE BÚSQUEDA EN ARREGLOS

31
4.1. Búsqueda binaria

Un método eficiente de búsqueda que puede aplicarse a las matrices es la


búsqueda binaria. Si partimos de que los elementos de la matriz están
almacenados en orden ascendente, el proceso de búsqueda podría describirse
en los siguientes pasos:

Se selecciona el elemento del centro o aproximadamente del centro de la


matriz.

Si el valor a buscar no coincide con el elemento seleccionado, y es mayor que


él, se continúa la búsqueda en la segunda mitad de la matriz. Si, por el
contrario, el valor a buscar es menor que el valor del elemento seleccionado, la
búsqueda continúa en la primera mitad de la matriz.

En ambos casos, se halla de nuevo el elemento central, correspondiente al


nuevo intervalo de búsqueda, repitiéndose el ciclo.

El proceso se repite hasta que se encuentre el valor buscado, o bien hasta que el
intervalo de búsqueda sea nulo, lo que querrá decir que el elemento buscado
NO FIGURA en la matriz.

Y el código correspondiente a este algoritmo sería:

public class BusquedaBinaria {


public static int busquedaBin(double[] matriz, double valorBuscado) {
// Este método devuelve como resultado la posicion

32
// del valor. Si el valor no se localiza, devuelve -1

if (matriz.length == 0) {
return -1;
}

int mitad, inferior = 0;


int superior = matriz.length – 1;

do {
mitad = (inferior + superior) / 2;
if (valorBuscado > matriz[mitad]) {
inferior = mitad + 1;
} else {
superior = mitad – 1;
}
} while (matriz[mitad] != valorBuscado && inferior <= superior);

if (matriz[mitad] == valorBuscado) {
return mitad;
} else {
return -1;
}
}
}
4.2. Búsqueda secuencial

El método de búsqueda secuencial consiste en ir comparando el elemento o


criterio de búsqueda con cada uno de los elementos en el arreglo, esto se hace
recorriendo el arreglo y deteniéndose en cada elemento y hacer la comparación,

33
en caso de ser verdadera la comparación, guardar la posición el elemento o
dato.

He aquí el código:
public int busquedaSecuencial(int []arreglo,int dato){
int posicion = -1;
for(int i = 0; i < arreglo.length; i++){//recorremos todo el arreglo
if(arreglo[i] == dato){//comparamos el elemento en el arreglo con el
buscado
posicion = i;//Si es verdadero guardamos la posicion
break;//Para el ciclo
}
}
return posicion;
}
Este método nos halla la posición del elemento o dato buscado, pero en su
primera coincidencia, si queremos que nos halle la posición de la última
coincidencia, lo único que tenemos que hacer es eliminar la línea donde
aparece 'break'.

Si el resultado del método anterior es -1, significa que el elemento no se


encuentra en el arreglo.

34
Ahora cabe la pregunta, ¿y si el elemento que deseo buscar aparece varias
veces en el arreglo y yo deseo conocer cada una de estas posiciones, como
hago?

Lo que hacemos es deshacernos de la línea 'break' para que el vector sea


recorrido en su totalidad, y de alguna forma ir almacenando cada una de las
posiciones resultantes de las comparaciones verdaderas.

He aquí el código:

public String busquedaSecuencial2(int []arreglo,int valor){


String posicion = "";
for(int i = 0; i < arreglo.length; i++){
if(arreglo[i] == valor){
posicion += i+",";
}
}
return posicion;
}

CAPITULO III: PROGRAMACION ORIENTADA A OBJETOS EN


JAVA
La programación orientada a objetos (POO) es un paradigma de programación que usa
objetos para crear aplicaciones. Está basada en tres pilares fundamentales: herencia,
polimorfismo, encapsulación. Su uso se popularizó a principios de la década de 1990.
En la actualidad, existe una gran variedad de lenguajes de programación que soportan la
orientación a objetos, entre ellos Java.

Ventajas de la Programación Orientada A Objetos

 Fomenta la reutilización y ampliación del código.


 Permite crear sistemas más complejos.
 La programación se asemeja al mundo real.

35
 Agiliza el desarrollo de software.
 Facilita el trabajo en equipo.

Lo interesante de la POO es que proporciona conceptos y herramientas con las cuales se


modela y representa el mundo real tan fielmente como sea posible.

Para entender este modelo vamos a revisar 2 conceptos fundamentales:

1. Clases

En el mundo real, normalmente tenemos muchos objetos del mismo tipo. Por
ejemplo, nuestro teléfono móvil es sólo uno de los miles que hay en el mundo. Si
hablamos en términos de la programación orientada a objetos, podemos decir que
nuestro objeto móvil es una instancia de una clase conocida como “móvil”. Los
móviles tienen características (marca, modelo, sistema operativo, pantalla, teclado,
etc.) y comportamientos (hacer y recibir llamadas, enviar mensajes multimedia,
transmisión de datos, etc.).

Cuando se fabrican los móviles, los fabricantes aprovechan el hecho de que los
móviles comparten esas características comunes y construyen modelos o plantillas
comunes, para que a partir de esas se puedan crear muchos móviles del mismo
modelo. A ese modelo o plantilla le llamamos clase, y a los equipos que sacamos a
partir de ella la llamamos objetos.

Esto mismo se aplica a los objetos de software, se puede tener muchos objetos del
mismo tipo y mismas características.

Definición teórica: La clase es un modelo o prototipo que define las variables y


métodos comunes a todos los objetos de cierta clase. También se puede decir que
una clase es una plantilla genérica para un conjunto de objetos de similares
características.

Por otro lado, una instancia de una clase es otra forma de llamar a un objeto. En
realidad, no existe diferencia entre un objeto y una instancia. Sólo que el objeto es

36
un término más general, pero los objetos y las instancias son ambas
representaciones de una clase.

2. OBJETOS

Entender que es un objeto es la clave para entender cualquier lenguaje orientado


a objetos.

Tomemos como ejemplo un ordenador. No necesitamos ser expertos para saber


que un ordenador está compuesto internamente por varios componentes: placa
base, procesador, disco duro, tarjeta de video, etc.…

El trabajo en conjunto de todos estos componentes hace funcionar un ordenador,


sin embargo, no necesitamos saber cómo trabajan cada uno de estos
componentes. Cada componente es una unidad autónoma, y todo lo que
necesitamos saber es cómo interactúan entre sí los componentes, saber por
ejemplo si el procesador y las memorias son compatibles con la placa base, o
conocer donde se coloca la tarjeta de video. Cuando conocemos como
interaccionan los componentes entre sí, podremos armar fácilmente un
ordenador.

¿Qué tiene que ver esto con la programación?

La programación orientada a objetos trabaja de esta manera. Todo el programa


está construido en base a diferentes componentes (objetos), cada uno tiene un rol
específico en el programa y todos los componentes pueden comunicarse entre
ellos de formas predefinidas.

37
Todo objeto del mundo real tiene 2 componentes: variables de clase y métodos.

Por ejemplo, los automóviles pueden tener como variables de clase (marca,
modelo, color, velocidad máxima, etc.) y como métodos (frenar, acelerar,
retroceder, llenar combustible, cambiar llantas, etc.).

Los objetos de Software, al igual que los objetos del mundo real, también tienen
variables de clase y métodos. Un objeto de software mantiene sus características
en una o más “variables”, e implementa su comportamiento con “métodos”. Un
método es una función o subrutina asociada a un objeto.

Imaginemos que tenemos aparcado en el garaje un Ford Focus color azul que
corre hasta 260 km/h. Si pasamos ese objeto del mundo real al mundo del
software, tendremos un objeto Automóvil con sus características
predeterminadas:

Marca = Ford

Modelo = Focus

Color = Azul

Velocidad Máxima = 260 km/h

Por lo tanto, dentro de una clase tendremos como variables de clase las
características descritas anteriormente y como métodos tendremos en este caso
concreto (frenar, acelerar, retroceder, llenar combustible, etc.…).

Vamos a ver un ejemplo práctico de como se hace esto en Java:

38
class Automovil {
// VARIABLES DE CLASE
private String marca;
private String modelo;
private String color;
private String velocidadMaxima;

// CONSTRUCTOR QUE INICIALIZA LAS VARIABLES DE CLASE


public Automovil(String marca, String modelo, String color, String
velocidadMaxima) {
this.marca = marca;
this.modelo = modelo;
this.color = color;
this.velocidadMaxima = velocidadMaxima;
}
// METODOS GETTER Y SETTER PARA PODER RECUPERAR O CAMBIAR
// LOS DATOS DE LAS VARIABLES DE CLASE
public String getMarca() {
return marca;
}

public void setMarca(String marca) {


this.marca = marca;
}

public String getModelo() {


return modelo;
}

public void setModelo(String modelo) {

39
this.modelo = modelo;
}

public String getColor() {


return color;
}

public void setColor(String color) {


this.color = color;
}

public String getVelocidadMaxima() {


return velocidadMaxima;
}

public void setVelocidadMaxima(String velocidadMaxima) {


this.velocidadMaxima = velocidadMaxima;
}

3. OTROS CONCEPTOS DE LA PROGRAMACION ORIENTADA A


OBJETOS
3.1. Constructores y destructores
Los constructores y destructores son dos tipos de métodos especiales que se
ejecutan, respectivamente, al crear un nuevo objeto y cuando el recolector de
basura detecta que ya no lo estamos utilizando y es posible eliminarlo de la
memoria. Hasta ahora no hemos hecho uso nunca ni de los constructores ni de
los destructores puesto que los ejemplos que hemos venido utilizando eran
bastante simples, pero a partir de ahora vamos a empezar a utilizarlos bastante

40
a menudo. Sobre todo, en el caso de los constructores, ya que los destructores
no se suelen usar más que en contadas ocasiones.

Para crear un objeto se necesita reservar suficiente espacio en memoria e


inicializar los valores de los campos que representan el estado del objeto.
Este trabajo es realizado por un tipo especial de método denominado
constructor.

3.1.1. Constructor
Un método constructor de una clase es un método especial que:
tiene el mismo nombre que la clase y
no tiene tipo de retorno.
inicializa el estado de un objeto.
La sintaxis para la declaración de un método constructor es:
[atributos] [modificadores] <identificador> ( [parámetros] )
[inicializador]
{
// Cuerpo del constructor.
}
Donde:
atributos (opcional) es información declarativa adicional.
modificadores (opcional) se restringen a extern y a los modificadores de
acceso.
identificador es el nombre del método constructor (igual al nombre de la
clase).
parámetros (opcional) es la lista de parámetros pasados al constructor.
inicializador (opcional). Con el inicializador, el constructor invoca
previamente a otro constructor.
El inicializador puede ser uno de los siguientes:
· base([listaDeParámetros])
· this([listaDeParámetros])
Cuerpo del constructor es el bloque de programa que contiene las
instrucciones para inicializar la instancia de clase (objeto).

41
Ejemplo:
class Producto
{
private int clave;
private double precio;
public Producto( int c, double p)
{
clave = c;
precio = p;
}
public double daPrecio( )
{
return precio;
}
}

3.1.2. Destructor
En contraposición al constructor, el destructor elimina el vínculo y libera
el espacio de memoria de un objeto, para que pueda ser ocupado
nuevamente.

La sintaxis para declarar un destructor es:


[atributos] ~ <identificador> ( )
{
// Cuerpo del destructor.
}

Notas:
 Una clase solamente puede tener un destructor.
 Los destructores no pueden heredarse o sobrecargarse.
 Los destructores no pueden invocarse, sino que son invocados
automáticamente.

42
 Un destructor no acepta modificadores ni parámetros. Por
ejemplo, la siguiente es una declaración de un destructor para la
clase Figura:
~ Figura()
{
// Instrucciones para limpiar.
}

El destructor llama implícitamente al método Object.Finalize( ) en la


clase base object. Por lo tanto, el código destructor precedente es
traducido automáticamente a:
protected override void Finalize( )
{
try
{
// Instrucciones para limpiar.
}
finally
{
base.Finalize( ) ;
}
}

Ejemplo:
// Destructores.cs : Maneja tres destructores de clases encadenadas.
using System;
using C = System.Console;
class Primera
{
~ Primera( )
{
C.WriteLine("Se invocó al destructor de Primera...");

43
}
}
class Segunda : Primera
{
~ Segunda( )
{
C.WriteLine("Se invocó al destructor de Segunda...");
}
}
class Tercera : Segunda
{
~ Tercera( )
{
C.WriteLine("Se invocó al destructor de Tercera...");
}
}
public class Principal
{
public static void Main( )
{
Tercera t = new Tercera ( );
}
}

Aplicaciones de constructores y destructores


En esta sección se presenta una serie de ejemplos donde se
implementarán:
1.- clases que sólo poseen el constructor predeterminado ,
2.- clases con un constructor definido por el programador y
3.- clases con un constructor definido por el programador y el
predefinido (que deberá ser reescrito por el programador).
El constructor predeterminado es incluído automáticamente.

44
Cuando el programador define un constructor, el predeterminado se
anula. En caso de requerir el constructor predeterminado junto con un
constructor definido por el programador, deberá volverse a escribir el
constructor predefinido, de acuerdo al siguiente formato :
public <nombreClase>( )
{
}

Ejemplo 1
// Uso del constructor predeterminado.(No se define otro constructor)
using System;
using C = System.Console;
class Persona
{
private string nombre;
private int edad;
public void asignaNombre( string n)
{
nombre = n;
}
public void asignaEdad( int e)
{
edad = e;
}
public string daNombre( )
{
return nombre;
}
public int daEdad( )
{
return edad ;
}

45
}
public class Principal
{
public static void Main( )
{
Persona p = new Persona( ) ; // Se invoca al constructor
//predeterminado.
p.asignaNombre("Luis");
p.asignaEdad(25);
C.WriteLine("Nombre: {0} , Edad: {1}", p.daNombre(),
p.daEdad());
}
}

Ejemplo 2
// Uso de un constructor con dos parámetros.(No se requiere un
constructor predefinido)
using System;
using C = System.Console;
class Persona
{
private string nombre;
private int edad;
public Persona( string n, int e)
{
nombre = n;
edad = e;
}
public string daNombre( )
{
return nombre;
}

46
public int daEdad( )
{
return edad ;
}
}
public class Principal
{
public static void Main( )
{
Persona p = new Persona( "Luis", 25) ;
C.WriteLine("Nombre: {0} , Edad: {1}", p.daNombre(),
p.daEdad());
}
}

Ejemplo 3
// Uso de un constructor con dos parámetros y el constructor
predefinido.
using System;
using C = System.Console;
class Persona
{
private string nombre;
private int edad;
public Persona(string n, int e)
{
nombre = n;
edad = e;
}
public Persona() // Constructor predeterminado, vuelto a escribir.
{
}

47
public string daNombre()
{
,.....return nombre;
}
public int daEdad()
{
.....return edad;
}
public void asignaNombre(string n)
{
.....nombre = n;
}
public void asignaEdad(int e)
{
...edad = e;
}
}
public class Principal
{
public static void Main()
{
Persona pa = new Persona("Luis", 25);
Persona pb = new Persona(); // Se invoca al constructor
................................................// predeterminado
pb.asignaNombre("Pepe");
pb.asignaEdad(19);
C.WriteLine("Nombre: {0} , Edad: {1}", pa.daNombre(),
pa.daEdad());
C.WriteLine("Nombre: {0} , Edad: {1}", pb.daNombre(),
pb.daEdad());
C.Read();
}

48
}

3.2. Encapsulación

La encapsulación consiste en unir en tener las variables de clase declaradas


como private para evitar que cuando instanciemos un objeto podamos acceder
a ellas (por seguridad). ¿Y entonces como accedemos a los valores de esas
variables de clase? Mediante los métodos getter y setter que declaramos
anteriormente.

Imaginemos que se crea una clase, una docena de programadores tienen acceso
a dicha clase y la utilizan a discreción, posteriormente dicha clase comienza a
comportarse de una manera inesperada debido a que los valores que algunas
variables han tomado no fueron anticipados y todo comienza a desmoronarse.
Para corregir el problema se crea una versión más nueva de dicha clase y listo.

Bueno, a esto le llamamos flexibilidad y capacidad de mantenimiento, ambas


son características y beneficios de la programación Orientada a Objetos (OO)
pero para que una clase pueda cumplir dichas funciones los programadores
debemos de hacer algo. Imaginemos que creamos una clase con variables de
instancia públicas a las cuales podemos acceder sin problemas desde fuera de
la misma clase...

Analizando el código anterior podemos darnos cuenta de que las variables


enteras tipo y clase son públicas y pueden ser accedidas directamente a través

49
de una instancia de la clase MiClase, esto compila sin ningún problema,
digamos que es 'legal', sin embargo, ¿qué pasa si ingresamos un valor que no se
supone debe de tener una variable (en este caso el -5 que le asignamos a tipo)?,
simplemente no hay nada que nos detenga para hacerlo. La única manera de
proteger el código es escribiendo un método que nos permita regular los
valores que cada variable puede tener y escondiendo las variables para que no
se pueda acceder a ellas de manera directa, esto es el principio básico de
encapsulamiento.

Si se desea flexibilidad, buen mantenimiento y extensibilidad, nuestro diseño


en el código debe de incluir encapsulamiento, para ello debemos de hacer lo
siguiente:

Mantener las variables de instancia protegidas (puede ser con un modificador


de acceso, p.ej., private).

Hacer métodos de acceso públicos para forzar al acceso a las variables por
medio de dichos métodos en lugar de acceder directamente.

Utilizar las convenciones de código para los nombres de los métodos, p. ej., set
y get.

El ejemplo anterior modificado para un buen encapsulamiento quedaría


así:

50
Si nos fijamos un poquito, en el método setTipo() no existen validaciones para
prevenir que un valor no válido sea asignado a la variable, sin embargo, el
proveer de un método de este tipo desde el diseño inicial de la aplicación nos
permite posteriormente modificar el comportamiento de la misma sin afectar
los métodos utilizados, tal vez en un futuro se desee que dicha variable
solamente pueda tener uno entre un rango de valores y se podrán aplicar
posteriormente los cambios sin que haya repercusiones negativas.

3.3. Herencia
La herencia es uno de los conceptos más cruciales en la POO. La herencia
consiste en que una clase puede heredar las variables y los métodos de otra
clase (la clase que hereda es llamada superclase o clase padre). Esto significa

51
que una subclase, aparte de los atributos y métodos propios, tiene incorporados
los atributos y métodos heredados de la superclase. De esta manera se crea una
jerarquía de herencia.

Si partimos de la clase Automovil que creamos anteriormente podríamos crear


clases hijas de Automovil, la cuales heredarán todo lo que contenga la clase
Automovil.

¿Como se hereda en Java?

Para crear herencia se usa la palabra reservada extends:

class Coche extends Automovil {

}
Como puedes ver en este caso estamos haciendo que la clase Coche herede de
la clase Automovil.

Entre las principales ventajas que ofrece la herencia en el desarrollo de


aplicaciones, están:
 Reutilización del código: En aquellos casos donde se necesita crear una
clase que, además de otros propios, deba incluir los métodos definidos en
otra, la herencia evita tener que reescribir todos esos métodos en la nueva
clase.
 Mantenimiento de aplicaciones existentes: Utilizando la herencia, si
tenemos una clase con una determinada funcionalidad y tenemos la
necesidad de ampliar dicha funcionalidad, no necesitamos modificar la
clase existente (la cual se puede seguir utilizando para el tipo de programa
para la que fue diseñada) sino que podemos crear una clase que herede a la
primera, adquiriendo toda su funcionalidad y añadiendo la suya propia.

Ejemplo: Comencemos con un breve ejemplo que ilustra varias de las


características clave de la herencia. El siguiente programa crea una
superclase llamada DosDimensiones, que almacena el ancho y la altura de
un objeto bidimensional, y una subclase llamada Triangulo. Observe cómo
se usa la palabra clave extends para crear una subclase.
//Clase para objetos de dos dimensiones
class DosDimensiones{
double base;

52
double altura;
void mostrarDimension(){
System.out.println("La base y altura es: "+base+" y "+altura);
}
}
//Una subclase de DosDimensiones para Triangulo
class Triangulo extends DosDimensiones{
String estilo;
double area(){
return base*altura/2;
}
void mostrarEstilo(){
System.out.println("Triangulo es: "+estilo);
}
}
class Lados3{
public static void main(String[] args) {
Triangulo t1=new Triangulo();
Triangulo t2=new Triangulo();
t1.base=4.0;
t1.altura=4.0;
t1.estilo="Estilo 1";
t2.base=8.0;
t2.altura=12.0;
t2.estilo="Estilo 2";
System.out.println("Información para T1: ");
t1.mostrarEstilo();
t1.mostrarDimension();
System.out.println("Su área es: "+t1.area());

53
System.out.println();
System.out.println("Información para T2: ");
t2.mostrarEstilo();
t2.mostrarDimension();
System.out.println("Su área es: "+t2.area());
}
}

Salida:
Información para T1:
Triangulo es: Estilo 1
La base y altura es: 4.0 y 4.0
Su área es: 8.0

Información para T2:


Triangulo es: Estilo 2
La base y altura es: 8.0 y 12.0
Su área es: 48.0

Nota: En el programa anterior, cuando se crea un objeto de clase


Triangulo, una copia de todos los métodos y campos de la superclase
adquiere memoria en este objeto. Es por eso que, al usar el objeto de la
subclase, también podemos acceder a los miembros de una superclase.

Tenga en cuenta que durante la herencia solo se crea el objeto de la


subclase, no de la superclase.

Control de Acceso a Miembros en Herencia

A menudo una variable de instancia de una clase se declarará privada


(private) para evitar su uso no autorizado o alteración. Heredar una clase
no anula la restricción de acceso privado. Por lo tanto, aunque una

54
subclase incluye a todos los miembros de su superclase, no puede acceder
a los miembros de la superclase que se han declarado privados.

Por ejemplo, si, como se muestra aquí, la base y la altura se vuelven


privados en DosDimensiones, entonces Triangulo no podrá acceder a ellos.

Ejemplo:

//Clase para objetos de dos dimensiones


class DosDimensiones{
private double base;
private double altura;
void mostrarDimension(){
System.out.println("La base y altura es: "+base+" y "+altura);
}
}
//Una subclase de DosDimensiones para Triangulo
class Triangulo extends DosDimensiones{
String estilo;
double area(){
return base*altura/2; //Error! no se puede acceder
}
void mostrarEstilo(){
System.out.println("Triangulo es: "+estilo);
}
}
La clase Triangulo no se compilará porque la referencia a la base y altura
dentro del método area() causa una infracción de acceso. Como la base y
altura se declaran privados, solo son accesibles para otros miembros de su
propia clase. Las subclases no tienen acceso a ellas.

55
Recuerde que un miembro de la clase que ha sido declarado
[java]private[java] seguirá siendo privado para su clase. No es accesible
por ningún código fuera de su clase, incluidas las subclases.

Al principio, podría pensar que el hecho de que las subclases no tengan


acceso a los miembros privados de las superclases es una restricción seria
que impediría el uso de miembros privados en muchas situaciones. Sin
embargo, eso no es verdad. Los programadores de Java suelen utilizar
métodos de acceso para proporcionar acceso a los miembros privados de
una clase.

Aquí hay una reescritura de las clases DosDimensiones y Triangulo que


usa métodos para acceder a las variables de instancia privadas base y
altura:

//Clase para objetos de dos dimensiones


class DosDimensiones{
private double base;
private double altura;
//Métodos de acceso para base y altura
double getBase(){return base;}
double getAltura(){return altura;}
void setBase(double b){base=b;}
void setAltura (double h){altura=h;}
void mostrarDimension(){
System.out.println("La base y altura es: "+base+" y "+altura);
}
}
//Una subclase de DosDimensiones para Triangulo
class Triangulo extends DosDimensiones{
String estilo;
double area(){

56
return getBase()*getAltura()/2;
}
void mostrarEstilo(){
System.out.println("Triangulo es: "+estilo);
}
}
class Lados3{
public static void main(String[] args) {
Triangulo t1=new Triangulo();
Triangulo t2=new Triangulo();
t1.setBase(4.0);
t1.setAltura(4.0);
t1.estilo="Estilo 1";
t2.setBase(8.0);
t2.setAltura(12.0);
t2.estilo="Estilo 2";
System.out.println("Información para T1: ");
t1.mostrarEstilo();
t1.mostrarDimension();
System.out.println("Su área es: "+t1.area());
System.out.println();
System.out.println("Información para T2: ");
t2.mostrarEstilo();
t2.mostrarDimension();
System.out.println("Su área es: "+t2.area());
}
}
Salida:
Información para T1:

57
Triangulo es: Estilo 1
La base y altura es: 4.0 y 4.0
Su área es: 8.0

Información para T2:


Triangulo es: Estilo 2
La base y altura es: 8.0 y 12.0
Su área es: 48.0

Constructores y herencia

En una jerarquía, es posible que tanto las superclases como las subclases
tengan sus propios constructores. Esto plantea una pregunta importante:
¿qué constructor es responsable de construir un objeto de la subclase, el de
la superclase, el de la subclase o ambos? La respuesta es esta: el
constructor para la superclase construye la porción de la superclase del
objeto, y el constructor para la subclase construye la parte de la subclase.

Esto tiene sentido porque la superclase no tiene conocimiento ni acceso a


ningún elemento en una subclase. Por lo tanto, su construcción debe estar
separada. En la práctica, la mayoría de las clases tendrán constructores
explícitos (no predeterminados). Aquí verá cómo manejar esta situación.

Cuando solo la subclase define un constructor, el proceso es sencillo:


simplemente construye el objeto de la subclase. La porción de superclase
del objeto se construye automáticamente utilizando su constructor
predeterminado. Por ejemplo, aquí hay un programa para Triangulo que
define un constructor. También hace que el estilo sea privado, ya que
ahora lo establece el constructor.

//Clase para objetos de dos dimensiones


//DosDimensiones.java
class DosDimensiones{

58
private double base;
private double altura;
//Métodos de acceso para base y altura
double getBase(){return base;}
double getAltura(){return altura;}
void setBase(double b){base=b;}
void setAltura (double h){altura=h;}
void mostrarDimension(){
System.out.println("La base y altura es: "+base+" y "+altura);
}
}
//Una subclase de DosDimensiones para Triangulo
//Triangulo.java
class Triangulo extends DosDimensiones{
private String estilo;
//Constructor
Triangulo(String s, double b, double h){
setBase(b);
setAltura(h);
estilo=s;
}
double area(){
return getBase()*getAltura()/2;
}
void mostrarEstilo(){
System.out.println("Triangulo es: "+estilo);
}
}
class Lados3{

59
public static void main(String[] args) {
Triangulo t1=new Triangulo("Estilo 1",4.0,4.0);
Triangulo t2=new Triangulo("Estilo 2",8.0,12.0);
System.out.println("Información para T1: ");
t1.mostrarEstilo();
t1.mostrarDimension();
System.out.println("Su área es: "+t1.area());
System.out.println();
System.out.println("Información para T2: ");
t2.mostrarEstilo();
t2.mostrarDimension();
System.out.println("Su área es: "+t2.area());
}
}
Salida:
Información para T1:
Triangulo es: Estilo 1
La base y altura es: 4.0 y 4.0
Su área es: 8.0

Información para T2:


Triangulo es: Estilo 2
La base y altura es: 8.0 y 12.0
Su área es: 48.0
Aquí, el constructor de Triangulo inicializa los miembros de
DosDimensiones que hereda, junto con su propio campo de estilo.

Cuando tanto la superclase como la subclase definen constructores, el


proceso es un poco más complicado porque deben ejecutarse tanto la
superclase como los constructores de subclase. En este caso, debe usar
otra de las palabras clave de Java, super, que tiene dos formas generales.

60
El primero llama a un constructor de superclase.
El segundo se usa para acceder a un miembro de la superclase que ha
sido ocultado por un miembro de una subclase.

Tipos de herencia en Java

A continuación, se muestran los diferentes tipos de herencia compatibles


con Java.

Herencia única: en la herencia única, las subclases heredan las


características de solo una superclase. En la imagen a continuación, la
clase A sirve como clase base para la clase derivada B.

Herencia Multinivel: en la herencia multinivel, una clase derivada


heredará una clase base y, además, la clase derivada también actuará como
la clase base de otra clase. En la imagen inferior, la clase A sirve como
clase base para la clase derivada B, que a su vez sirve como clase base
para la clase derivada C. En Java, una clase no puede acceder directamente
a los miembros de los “abuelos”.

61
Herencia Jerárquica: en la herencia jerárquica, una clase sirve como una
superclase (clase base) para más de una subclase. En la imagen inferior, la
clase A sirve como clase base para la clase derivada B, C y D.

Herencia Múltiple (a través de interfaces): en Herencia múltiple, una


clase puede tener más de una superclase y heredar características de todas
las clases principales. Tenga en cuenta que Java no admite herencia
múltiple con clases. En Java, podemos lograr herencia múltiple solo a

62
través de Interfaces. En la imagen a continuación, la Clase C se deriva de
la interfaz A y B.

Herencia Híbrida (a través de Interfaces): Es una mezcla de dos o más


de los tipos de herencia anteriores. Como Java no admite herencia múltiple
con clases, la herencia híbrida tampoco es posible con clases. En Java,
podemos lograr herencia híbrida solo a través de Interfaces.

63
Datos importantes acerca de la herencia en Java

 Superclase predeterminada: excepto la clase Object, que no tiene


superclase, cada clase tiene una y solo una superclase directa (herencia
única). En ausencia de cualquier otra superclase explícita, cada clase
es implícitamente una subclase de la clase Object.
 La superclase solo puede ser una: una superclase puede tener
cualquier cantidad de subclases. Pero una subclase solo puede tener
una superclase. Esto se debe a que Java no admite herencia múltiple
con clases. Aunque con interfaces, la herencia múltiple es compatible
con java.
 Heredar constructores: una subclase hereda todos los miembros
(campos, métodos y clases anidadas) de su superclase. Los
constructores no son miembros, por lo que no son heredados por
subclases, pero el constructor de la superclase puede invocarse desde
la subclase.
 Herencia de miembros privados: una subclase no hereda los
miembros privados de su clase principal. Sin embargo, si la superclase
tiene métodos públicos o protegidos (como getters y setters) para
acceder a sus campos privados, estos también pueden ser utilizados
por la subclase.

3.4. Polimorfismo

El polimorfismo es la habilidad de una función, método, variable u objeto de


poseer varias formas distintas. Podríamos decir que un mismo identificador
comparte varios significados diferentes.

El propósito del polimorfismo es implementar un estilo de programación


llamado envío de mensajes en el que los objetos interactúan entre ellos
mediante estos mensajes, que no son más que llamadas a distintas funciones.

Java tiene 4 grandes formas de polimorfismo:

 Polimorfismo de asignación
 Polimorfismo puro

64
 Sobrecarga
 Polimorfismo de inclusión

En programación orientada a objetos, polimorfismo es la capacidad que tienen


los objetos de una clase en ofrecer respuesta distinta e independiente en
función de los parámetros (diferentes implementaciones) utilizados durante su
invocación. Dicho de otro modo, el objeto como entidad puede contener
valores de diferentes tipos durante la ejecución del programa.

En JAVA el término polimorfismo también suele definirse como ‘Sobrecarga


de parámetros’, que así de pronto no suena tan divertido, pero como veremos
más adelante induce a cierta confusión. En realidad, suele confundirse con el
tipo de poliformismo más común, pero no es del todo exacto usar esta
denominación.

Ejemplo de Polimorfismo

Un ejemplo clásico de poliformismo es el siguiente. Podemos crear dos clases


distintas: Gato y Perro, que heredan de la superclase Animal. La clase Animal
tiene el método abstracto makesound() que se implementa de forma distinta en
cada una de las subclases (gatos y perros suenan de forma distinta). Entonces,
un tercer objeto puede enviar el mensaje de hacer sonido a un grupo de objetos
Gato y Perro por medio de una variable de referencia de clase Animal,
haciendo así un uso polimórfico de dichos objetos respecto del mensaje mover.

class Animal {

public void makeSound() {

System.out.println("Grr...");

class Cat extends Animal {

public void makeSound() {

System.out.println("Meow");

65
}

class Dog extends Animal {

public void makeSound() {

System.out.println("Woof");

Como todos los objetos Gato y Perro son objetos Animales, podemos hacer lo
siguiente

public static void main(String[ ] args) {

Animal a = new Dog();

Animal b = new Cat();

Creamos dos variables de referencia de tipo Animal y las apuntamos a los


objetos Gato y Perro. Ahora, podemos llamar a los métodos makeSound().

a.makeSound();

//Outputs "Woof"

b.makeSound();

//Outputs "Meow"

Como decía el polimorfismo, que se refiere a la idea de "tener muchas formas",


ocurre cuando hay una jerarquía de clases relacionadas entre sí a través de la
herencia y este es un buen ejemplo.

Por lo general diremos que existen 3 tipos de polimorfismo:

66
Sobrecarga: El más conocido y se aplica cuando existen funciones con el
mismo nombre en clases que son completamente independientes una de la otra.

Paramétrico: Existen funciones con el mismo nombre, pero se usan diferentes


parámetros (nombre o tipo). Se selecciona el método dependiendo del tipo de
datos que se envíe.

Inclusión: Es cuando se puede llamar a un método sin tener que conocer su


tipo, así no se toma en cuenta los detalles de las clases especializadas,
utilizando una interfaz común.

En líneas generales en lo que se refiere a la POO, la idea fundamental es


proveer una funcionalidad predeterminada o común en la clase base y de las
clases derivadas se espera que provean una funcionalidad más específica.

Polimorfismo paramétrico

Antes habíamos visto un ejemplo clásico de polimorfismo basado en


sobrecarga. Pero veamos ahora un ejemplo Paramétrico. Es importante
entender que la conversión automática sólo se aplica si no hay ninguna
coincidencia directa entre un parámetro y argumento.

Aquí el método demo() se sobrecarga 3 veces: el primer método tiene 1


parámetro int, el segundo método tiene 2 parámetros int y el tercero tiene un
parámetro doble. Por lo que para lidiar con esta variedad el método que se
llamará está determinado por los argumentos que pasamos al llamar a los
métodos. Esto sucede en tiempo de compilación en tiempo de ejecución, por lo
que este tipo de polimorfismo se conoce también como polimorfismo en
tiempo de compilación.

class Overload

void demo (int a)

System.out.println ("a: " + a);

67
}

void demo (int a, int b)

System.out.println ("a and b: " + a + "," + b);

double demo(double a) {

System.out.println("double a: " + a);

return a*a;

class MethodOverloading

public static void main (String args [])

Overload Obj = new Overload();

double result;

Obj .demo(10);

Obj .demo(10, 20);

result = Obj .demo(5.5);

System.out.println("O/P : " + result);

Salida de datos:

68
a: 10

a and b: 10,20

double a: 5.5

O/P : 30.25

Polimorfismo de inclusión

La habilidad para redefinir por completo el método de una superclase en una


subclase es lo que se conoce como polimorfismo de inclusión (o redefinición).

En él, una subclase define un método que existe en una superclase con una lista
de argumentos (si se define otra lista de argumentos, estaríamos haciendo
sobrecarga y no redefinición).

Un ejemplo muy básico en donde la clase Bishop sobreescribe el método


move. Esto es el polimorfismo de inclusión.

abstract class Piece{

public abstract void move(byte X, byte Y);

class Bishop extends Piece{

@Override

public void move(byte X, byte Y){

Diferencias entre polimorfismo y sobrecarga

69
El polimorfismo presenta unas claras ventajas aplicado desde las interfaces, ya
que nos permite crear nuevos tipos sin necesidad de modificar las clases ya
existentes. Basta con recompilar todo el código que incluye los nuevos tipos
añadidos sin retocar la clase anteriormente creada para añadir una nueva
implementación lo que podría suponer una revisión completa de todo el código
donde se instancia la clase.

Por contra, un método está sobrecargado si dentro de una clase existen dos o
más declaraciones de dicho método con el mismo nombre, pero con parámetros
distintos, por lo que no hay que confundirlo con polimorfismo.

Esto puede parecer un poco confuso, pero en definitiva el Polimorfismo


consiste en redefinir un método de una clase padre en una clase hija. Mientras
que sobrecarga es definir un nuevo método igual que otro viejo, pero
cambiando el tipo o la cantidad de parámetros.

El compilador, viendo los parámetros, sabe a qué método llamar en función del
parámetro que estás pasando. La sobrecarga se resuelve en tiempo de
compilación utilizando los nombres de los métodos y los tipos de sus
parámetros; el polimorfismo se resuelve en tiempo de ejecución del programa,
esto es, mientras se ejecuta, en función de la clase a la que pertenece el objeto.

Preguntas Frecuentes sobre polimorfismo en Java

¿Qué es el término firma?

Como ya se ha tratado en este artículo, en Java dos o más métodos dentro de la


misma clase pueden compartir el mismo nombre, siempre que sus
declaraciones de parámetros sean diferentes. Cuando esto sucede, se dice que
estamos usando sobrecarga de métodos (method overloading). En general
sobrecargar un método consiste en declarar versiones diferentes de él. Y aquí
es donde el compilador se ocupa del resto y donde el término firma cobra
importancia. Una firma es el nombre de un método más su lista de parámetros.
Por lo tanto, cada método en una misma clase, en términos de sobrecarga,
obtiene una firma diferente.

¿Diferencias entre los términos Overloading y Overriding?

70
Overloading significa que un mismo método tiene diferentes firmas mientras
que Overriding es el mismo método, por tanto, misma firma, al que diferentes
clases conectan a través de la herencia. En algunos textos encontramos otra
explicación en donde se resume la sobrecarga como un ejemplo de
polimorfismo en tiempo de compilación y la sobreescritura como un ejemplo
de polimorfismo en tiempo de ejecución.

¿Se pueden sobrecargar métodos estáticos?

Sí, es posible tener dos más métodos estáticos con el mismo nombre siempre
que se diferencien en los parámetros de entrada.

¿Es posible sobrecargar la clase main() en Java?

Sí, es posible siempre que definamos correctamente los parámetros de entrada


como en el siguiente ejemplo.

class Demo{

public static void main(String[] args) {

System.out.println("Hello Folks"); // Hello Folks

Demo.main("Ducks");

// Sobrecargando

public static void main(String arg1) {

System.out.println("Hello, " + arg1); // Hello Ducks

Demo.main("Dogs","Cats");

public static void main(String arg1, String arg2) {

System.out.println("Hello, " + arg1 + " and " + arg2); // Hello Dogs and
Cats

71
}

72

También podría gustarte