Está en la página 1de 76

INF-5140 Lenguaje de Programación II

Profesor Melvyn Quiñones

Unidad 3.
Programación Orientada a Objetos
Lenguaje de Programación II Prof. Melvyn Quiñones

INDICE
1. Introducción ......................................................................................................................... 4
Origen de la POO ............................................................................................................................. 5
Conceptos fundamentales .............................................................................................................. 6
Características de la POO ................................................................................................................ 8
Tipos de POO ................................................................................................................................. 10
Algunos lenguajes orientados a objetos ....................................................................................... 10
2. Objetos y clases .................................................................................................................. 11
Objeto............................................................................................................................................ 11
Clases............................................................................................................................................. 11
Instancias....................................................................................................................................... 12
3. Modificadores de Acceso .................................................................................................... 16
Modificador de acceso por defecto (default) ............................................................................... 16
Modificador de acceso privado (private) ...................................................................................... 17
Modificador de acceso protegido (protected) .............................................................................. 18
Modificador de acceso público (public) ........................................................................................ 18
Modificadores que no son de acceso ............................................................................................ 19
4. Tipos de atributos ............................................................................................................... 20
Variables de instancia ................................................................................................................... 20
Variables de clase (static) .............................................................................................................. 21
Constantes o variables finales (final) ............................................................................................ 23
Clases contenedoras o Wrappers.................................................................................................. 24
5. Clases estándar de java ....................................................................................................... 24
Objetos de la clase Character ........................................................................................................ 24
Objetos de la clase String .............................................................................................................. 25
Operaciones con instancias de la clase String ........................................................................... 25
Otros métodos para trabajar con objetos de la clase String ..................................................... 27
Clase Array..................................................................................................................................... 27
Objetos de la clase Array ........................................................................................................... 27
Operaciones con Arrays ............................................................................................................. 28
Array de objetos ........................................................................................................................ 30
Arrays multidimensionales ........................................................................................................ 31
6. Métodos en Java ................................................................................................................. 33
Return y Void................................................................................................................................. 34
Recursión ....................................................................................................................................... 36
Sobrecarga de métodos (Overload) .............................................................................................. 36
Tipos de métodos .......................................................................................................................... 37
Métodos de instancia ................................................................................................................ 37
Métodos de clase....................................................................................................................... 38

03- Programación Orientada a Objetos Página 2


Lenguaje de Programación II Prof. Melvyn Quiñones

7. Parámetros o argumentos ................................................................................................... 40


Declaración de parámetros ........................................................................................................... 40
Uso alternativo de this como referencia al parámetro implícito .................................................. 41
Paso por valor y paso por referencia ............................................................................................ 43
Variables locales ............................................................................................................................ 44
8. Constructores ..................................................................................................................... 45
Declaración de un constructor ...................................................................................................... 45
9. Herencia ............................................................................................................................. 47
Jerarquía de clases ........................................................................................................................ 49
Redefinición de elementos heredados ......................................................................................... 49
La clase object ............................................................................................................................... 50
Herencia y constructores .............................................................................................................. 51
Casting o moldes entre objetos con relación de herencia ............................................................ 51
Clases y métodos abstractos (abstract.......................................................................................... 52
Clases y métodos finales (final) ..................................................................................................... 54
10. Encapsulamiento en Java .................................................................................................. 55
¿Por qué debemos aplicar el principio de encapsulamiento? ...................................................... 56
11. Polimorfismo en Java ........................................................................................................ 57
Ejemplo de Polimorfismo .............................................................................................................. 57
Polimorfismo paramétrico ............................................................................................................ 58
Polimorfismo de inclusión ............................................................................................................. 59
Diferencias entre polimorfismo y sobrecarga ............................................................................... 60
12. Interfaces ......................................................................................................................... 62
Declaración de una interfaz .......................................................................................................... 62
Implementación de una interfaz en una clase .............................................................................. 63
Utilización de una interfaz como un tipo de dato ......................................................................... 66
13. Paquetes en Java .............................................................................................................. 67
Importar paquetes ........................................................................................................................ 71
Ejemplo de importación el paquete .............................................................................................. 71
Puntos a tener en cuenta .............................................................................................................. 72
Protección de acceso..................................................................................................................... 72
Los paquetes y el CLASSPATH ....................................................................................................... 73
EJERCICIOS DE EVALUACIÓN ................................................................................................... 74
REFERENCIAS .......................................................................................................................... 76

03- Programación Orientada a Objetos Página 3


Lenguaje de Programación II Prof. Melvyn Quiñones

1. Introducción
La Programación Orientada a
Objetos (POO, en español; OOP,
según sus siglas en inglés) es un
paradigma de programación
que viene a innovar la forma de
obtener resultados. Los objetos
manipulan los datos de entrada
para la obtención de datos de
salida específicos, donde cada
objeto ofrece una funcionalidad
especial.

Muchos de los objetos prediseñados de los lenguajes de programación actuales permiten


la agrupación en bibliotecas o librerías, sin embargo, muchos de estos lenguajes permiten
al usuario la creación de sus propias bibliotecas.

Está basada en varias técnicas del sexenio: herencia, cohesión, abstracción, polimorfismo,
acoplamiento y encapsulamiento.

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.

Los objetos son entidades que tienen un determinado "estado", "comportamiento


(método)" e "identidad":

La identidad es una propiedad de un objeto que lo diferencia del resto; dicho con otras
palabras, es su identificador (concepto análogo al de identificador de una variable o una
constante).

Los métodos (comportamiento) y atributos (estado) están estrechamente relacionados


por la propiedad de conjunto. Esta propiedad destaca que una clase requiere de métodos
para poder tratar los atributos con los que cuenta. El programador debe pensar
indistintamente en ambos conceptos, sin separar ni darle mayor importancia a alguno de
ellos. Hacerlo podría producir el hábito erróneo de crear clases contenedoras de
información por un lado y clases con métodos que manejen a las primeras por el otro. De
esta manera se estaría realizando una "programación estructurada camuflada" en un
lenguaje de POO.

03- Programación Orientada a Objetos Página 4


Lenguaje de Programación II Prof. Melvyn Quiñones

La programación orientada a objetos difiere


de la programación estructurada tradicional,
en la que los datos y los procedimientos
están separados y sin relación, ya que lo
único que se busca es el procesamiento de
unos datos de entrada para obtener otros
de salida. La programación estructurada
anima al programador a pensar sobre todo
en términos de procedimientos o funciones,
y en segundo lugar en las estructuras de
datos que esos procedimientos manejan. En
la programación estructurada solo se escriben funciones que procesan datos. Los
programadores que emplean POO, en cambio, primero definen objetos para luego
enviarles mensajes solicitándoles que realicen sus métodos por sí mismos.

Origen de la POO

Los conceptos de la POO tienen origen en


Simula 67, un lenguaje diseñado para
hacer simulaciones, creado por Ole-Johan
Dahl y Kristen Nygaard, del Centro de
Cómputo Noruego en Oslo. En este centro
se trabajaba en simulaciones de naves,
que fueron confundidas por la explosión
combinatoria de cómo las diversas
cualidades de diferentes naves podían
afectar unas a las otras. La idea surgió al agrupar los diversos tipos de naves en diversas
clases de objetos, siendo responsable cada clase de objetos de definir sus "propios" datos
y comportamientos. Fueron refinados más tarde en Smalltalk, desarrollado en Simula en
Xerox PARC (cuya primera versión fue escrita sobre Basic) pero diseñado para ser un
sistema completamente dinámico en el cual los objetos se podrían crear y modificar
"sobre la marcha" (en tiempo de ejecución) en lugar de tener un sistema basado en
programas estáticos.

La POO se fue convirtiendo en el estilo de programación dominante a mediados de los


años 1980, en gran parte debido a la influencia de C++, una extensión del lenguaje de
programación C. Su dominación fue consolidada gracias al auge de las interfaces gráficas
de usuario, para las cuales la POO está particularmente bien adaptada. En este caso, se
habla también de programación dirigida por eventos.

03- Programación Orientada a Objetos Página 5


Lenguaje de Programación II Prof. Melvyn Quiñones

Las características de orientación a objetos fueron


agregadas a muchos lenguajes existentes durante ese
tiempo, incluyendo Ada, BASIC, Lisp más Pascal, entre
otros. La adición de estas características a los lenguajes
que no fueron diseñados inicialmente para ellas
condujo a menudo a problemas de compatibilidad y en
la capacidad de mantenimiento del código. Los
lenguajes orientados a objetos "puros", por su parte,
carecían de las características de las cuales muchos
programadores habían venido a depender. Para saltar
este obstáculo, se hicieron muchas tentativas para crear nuevos lenguajes basados en
métodos orientados a objetos, pero permitiendo algunas características imperativas de
maneras "seguras". El lenguaje de programación Eiffel de Bertrand Meyer fue un
temprano y moderadamente acertado lenguaje con esos objetivos, pero ahora ha sido
esencialmente reemplazado por Java, en gran parte debido a la aparición de Internet y a
la implementación de la máquina virtual Java en la mayoría de navegadores web. PHP en
su versión 5 se ha modificado; soporta una orientación completa a objetos, cumpliendo
todas las características propias de la orientación a objetos.

Conceptos fundamentales

La POO es una forma de programar que trata de encontrar una solución a estos
problemas. Introduce nuevos conceptos, que superan y amplían conceptos antiguos ya
conocidos. Entre ellos destacan los siguientes:

 Clase: Una clase es una especie de "plantilla" en la que se definen los atributos y
métodos predeterminados de un tipo de objeto. Esta plantilla se crea para poder crear
objetos fácilmente. Al método de crear nuevos objetos mediante la lectura y
recuperación de los atributos y métodos de una clase se le conoce como instanciación.
 Herencia: Por ejemplo, herencia de la clase C a la clase D, es la facilidad mediante la
cual la clase D hereda en ella cada uno de los atributos y operaciones de C, como si
esos atributos y operaciones hubiesen sido definidos por la misma D. Por lo tanto,
puede usar los mismos métodos y variables registrados como "públicos" (public) en C.
Los componentes registrados como "privados" (private) también se heredan pero se
mantienen escondidos al programador y sólo pueden ser accedidos a través de otros
métodos públicos. Para poder acceder a un atributo u operación de una clase en
cualquiera de sus subclases pero mantenerla oculta para otras clases es necesario
registrar los componentes como "protegidos" (protected), de esta manera serán
visibles en C y en D pero no en otras clases.

03- Programación Orientada a Objetos Página 6


Lenguaje de Programación II Prof. Melvyn Quiñones

 Objeto: Instancia de una clase. Entidad provista de un conjunto de propiedades o


atributos (datos) y de comportamiento o funcionalidad (métodos), los mismos que
consecuentemente reaccionan a eventos. Se corresponden con los objetos reales del
mundo que nos rodea, o con objetos internos del sistema (del programa).
 Método: Algoritmo asociado a un objeto (o a una clase de objetos), cuya ejecución se
desencadena tras la recepción de un "mensaje". Desde el punto de vista del
comportamiento, es lo que el objeto puede hacer. Un método puede producir un
cambio en las propiedades del objeto, o la generación de un "evento" con un nuevo
mensaje para otro objeto del sistema.
 Evento: Es un suceso en el sistema (tal como una interacción del usuario con la
máquina, o un mensaje enviado por un objeto). El sistema maneja el evento enviando
el mensaje adecuado al objeto pertinente. También se puede definir como evento la
reacción que puede desencadenar un objeto; es decir, la acción que genera.
 Atributos: Características que tiene la clase.
 Mensaje: Una comunicación dirigida a un objeto, que le ordena que ejecute uno de
sus métodos con ciertos parámetros asociados al evento que lo generó.
 Propiedad o atributo: Contenedor de un tipo de datos asociados a un objeto (o a una
clase de objetos), que hace los datos visibles desde fuera del objeto y esto se define
como sus características predeterminadas, y cuyo valor puede ser alterado por la
ejecución de algún método.
 Estado interno: Es una variable que se declara privada, que puede ser únicamente
accedida y alterada por un método del objeto, y que se utiliza para indicar distintas
situaciones posibles para el objeto (o clase de objetos). No es visible al programador
que maneja una instancia de la clase.
 Miembros de un objeto: Atributos, identidad, relaciones y métodos.
 Identificación de un objeto: Un objeto se representa por medio de una tabla o entidad
que esté compuesta por sus atributos y funciones correspondientes.
 En comparación con un lenguaje imperativo, una "variable" no es más que un
contenedor interno del atributo del objeto o de un estado interno, así como la
"función" es un procedimiento interno del método del objeto.

03- Programación Orientada a Objetos Página 7


Lenguaje de Programación II Prof. Melvyn Quiñones

Características de la POO

Existe un acuerdo acerca de qué características contempla la "orientación a objetos". Las


características siguientes son las más importantes:

 Abstracción

Denota las características esenciales de un objeto, donde se capturan sus


comportamientos. Cada objeto en el sistema sirve como modelo de un "agente" abstracto
que puede realizar trabajo, informar y cambiar su estado, y "comunicarse" con otros
objetos en el sistema sin revelar "cómo" se implementan estas características. Los
procesos, las funciones o los métodos pueden también ser abstraídos, y, cuando lo están,
una variedad de técnicas son requeridas para ampliar una abstracción. El proceso de
abstracción permite seleccionar las características relevantes dentro de un conjunto e
identificar comportamientos comunes para definir nuevos tipos de entidades en el mundo
real. La abstracción es clave en el proceso de análisis y diseño orientado a objetos, ya que
mediante ella podemos llegar a armar un conjunto de clases que permitan modelar la
realidad o el problema que se quiere atacar.

 Encapsulamiento

Significa reunir todos los elementos que pueden considerarse pertenecientes a una misma
entidad, al mismo nivel de abstracción. Esto permite aumentar la cohesión (diseño
estructurado) de los componentes del sistema. Algunos autores confunden este concepto
con el principio de ocultación, principalmente porque se suelen emplear conjuntamente.

 Polimorfismo

Comportamientos diferentes, asociados a objetos distintos, pueden compartir el mismo


nombre; al llamarlos por ese nombre se utilizará el comportamiento correspondiente al
objeto que se esté usando. O, dicho de otro modo, las referencias y las colecciones de
objetos pueden contener objetos de diferentes tipos, y la invocación de un
comportamiento en una referencia producirá el comportamiento correcto para el tipo real
del objeto referenciado. Cuando esto ocurre en "tiempo de ejecución", esta última
característica se llama asignación tardía o asignación dinámica. Algunos lenguajes
proporcionan medios más estáticos (en "tiempo de compilación") de polimorfismo, tales
como las plantillas y la sobrecarga de operadores de C++.

 Herencia

Las clases no se encuentran aisladas, sino que se relacionan entre sí, formando una
jerarquía de clasificación. Los objetos heredan las propiedades y el comportamiento de

03- Programación Orientada a Objetos Página 8


Lenguaje de Programación II Prof. Melvyn Quiñones

todas las clases a las que pertenecen. La herencia organiza y facilita el polimorfismo y el
encapsulamiento, permitiendo a los objetos ser definidos y creados como tipos
especializados de objetos preexistentes. Estos pueden compartir (y extender) su
comportamiento sin tener que volver a implementarlo. Esto suele hacerse habitualmente
agrupando los objetos en clases, y estas en árboles o enrejados que reflejan un
comportamiento común. Cuando un objeto hereda de más de una clase, se dice que hay
herencia múltiple; siendo de alta complejidad técnica por lo cual suele recurrirse a la
herencia virtual para evitar la duplicación de datos.

 Modularidad

Se denomina "modularidad" a la propiedad que permite subdividir una aplicación en


partes más pequeñas (llamadas módulos), cada una de las cuales debe ser tan
independiente como sea posible de la aplicación en sí y de las restantes partes. Estos
módulos se pueden compilar por separado, pero tienen conexiones con otros módulos. Al
igual que la encapsulación, los lenguajes soportan la modularidad de diversas formas.

 Principio de ocultación

Cada objeto está aislado del exterior, es un módulo natural, y cada tipo de objeto expone
una "interfaz" a otros objetos que específica cómo pueden interactuar con los objetos de
la clase. El aislamiento protege a las propiedades de un objeto contra su modificación por
quien no tenga derecho a acceder a ellas; solamente los propios métodos internos del
objeto pueden acceder a su estado. Esto asegura que otros objetos no puedan cambiar el
estado interno de un objeto de manera inesperada, eliminando efectos secundarios e
interacciones inesperadas. Algunos lenguajes relajan esto, permitiendo un acceso directo
a los datos internos del objeto de una manera controlada y limitando el grado de
abstracción. La aplicación entera se reduce a un agregado o rompecabezas de objetos.

 Recolección de basura

La recolección de basura (garbage collection) es la técnica por la cual el entorno de


objetos se encarga de destruir automáticamente, y por tanto desvincular la memoria
asociada, los objetos que hayan quedado sin ninguna referencia a ellos. Esto significa que
el programador no debe preocuparse por la asignación o liberación de memoria, ya que el
entorno la asignará al crear un nuevo objeto y la liberará cuando nadie lo esté usando. En
la mayoría de los lenguajes híbridos que se extendieron para soportar el Paradigma de
Programación Orientada a Objetos como C++ u Object Pascal, esta característica no existe
y la memoria debe desasignarse expresamente.

03- Programación Orientada a Objetos Página 9


Lenguaje de Programación II Prof. Melvyn Quiñones

Tipos de POO

Para realizar programación orientada a objetos existen dos corrientes principales:

Basada en clases. Es la más ampliamente usada por los lenguajes de programación


orientada a objetos. Por ejemplo es usada por Java, C++ y C#. Se basa en crear una
estructura molde llamada clase donde se especifican los campos y métodos que tendrán
nuestros objetos. Cada vez que necesitamos un objeto creamos una instancia (o copia del
objeto) usando la clase como molde.

Basada en prototipos. Es soportado en Javascript, Python y Ruby. No hay clases, solo hay
objetos. El mecanismo para la reutilización está dado por la clonación de objetos. Se crean
directamente los objetos y cuando se quiere generar otro con la misma estructura se usa
clonación. Una vez clonado si queremos podemos agregar los campos y métodos
necesarios. Un objeto prototípico es un objeto que se utiliza como una plantilla a partir de
la cual se obtiene el conjunto inicial de propiedades de un objeto. Cualquier objeto puede
ser utilizado como el prototipo de otro objeto, permitiendo al segundo objeto compartir
las propiedades del primero.

Algunos lenguajes orientados a objetos

Simula (1967) es aceptado como el primer lenguaje que posee las características
principales de un lenguaje orientado a objetos. Fue creado para hacer programas de
simulación, en donde los "objetos" son la representación de la información.

Smalltalk (1972 a 1980) es posiblemente el ejemplo canónico, y con el que gran parte de la
teoría de la programación orientada a objetos se ha desarrollado, aunque existen otros
lenguajes orientados a objetos que son igual de importantes:

ABAP Fortran 90/95 Ruby


ABL Java Self
ActionScript JavaScript Smalltalk
ActionScript 3 Lexico Swift
C Sharp (C#) Objective-C Magik
Clarion Ocaml Vala
Clipper Oz VB.NET
D R Visual FoxPro
Python Pauscal (en español) Visual Basic 6.0
Gambas Perl Visual DataFlex
GObject Perl 6 Visual Objects
Genie PHP XBase++
Harbour PowerScript DRP
Eiffel Processing Scala
Object Pascal (Embarcadero Delphi)

03- Programación Orientada a Objetos Página 10


Lenguaje de Programación II Prof. Melvyn Quiñones

2. Objetos y clases
Objeto

Aunque parezca una obviedad, la base de


la Programación Orientada a Objetos es el
objeto. En la vida real todos los objetos
tienen una serie de características y un
comportamiento. Por ejemplo, una
puerta tiene color, forma, dimensiones,
material... (Goza de una serie de características) y puede abrirse, cerrarse... (Posee un
comportamiento). En POO, objeto es una combinación de unos datos específicos y de las
rutinas que pueden operar con esos datos. Los tipos de componentes de un objeto son:

Campos o atributos: Componentes de un objeto que almacenan datos. También se les


denomina “variables miembro”. Estos datos pueden ser de tipo primitivo (boolean, int,
double, char...) o, a su vez, de otro tipo de objeto (lo que se denomina agregación o
composición de objetos). La idea es que un atributo representa una propiedad
determinada de un objeto.

Rutinas o métodos: Es una componente de un objeto que lleva a cabo una determinada
acción o tarea con los atributos. En principio, todas las variables y rutinas de un programa
de Java deben pertenecer a una clase. De hecho, en Java no hay noción de programa
principal y las subrutinas no existen como unidades modulares independientes, sino que
forman siempre parte de alguna clase.

Clases

Una clase representa al conjunto de objetos que comparten una estructura y un


comportamiento comunes. Una clase es una combinación específica de atributos y
métodos y puede considerarse un tipo de dato de cualquier tipo no primitivo. Así, una
clase es una especie de plantilla o prototipo de objetos: define los atributos que
componen ese tipo de objetos y los métodos que pueden emplearse para trabajar con
esos objetos. Aunque, por otro lado, una clase también puede estar compuesta por
métodos estáticos que no necesitan de objetos (como las clases construidas en los
capítulos anteriores que contienen un método estático main). La declaración de una clase
sigue la siguiente sintaxis:
[modificadores] class IdentificadorClase {
// Declaraciones de atributos y metodos
...
}

03- Programación Orientada a Objetos Página 11


Lenguaje de Programación II Prof. Melvyn Quiñones

Convención de los programadores en Java: los identificadores de las clases deberían ser
simples, descriptivos y sustantivos y, en el caso de nombres compuestos, con la primera
letra de cada uno en mayúsculas. Es conveniente utilizar las palabras completas y evitar
los acrónimos, a menos que la abreviatura sea mucho más utilizada que la forma no
abreviada como en URL o HTML.

Instancias

Una instancia es un elemento tangible (ocupa memoria durante la ejecución del


programa) generado a partir de una definición de clase. Todos los objetos empleados en
un programa han de pertenecer a una clase determinada.

Aunque el término a veces se emplea de una forma imprecisa, un objeto es una instancia
de una clase predefinida en Java o declarada por el usuario y referenciada por una
variable que almacena su dirección de memoria. Cuando se dice que Java no tiene
punteros simplemente se indica que Java no tiene punteros que el programador pueda
ver, ya que todas las referencias a objeto son de hecho punteros en la representación
interna.

En general, el acceso a los atributos se realiza a través del operador punto, que separa al
identificador de la referencia del identificador del atributo (idReferencia.idAtributo). Las
llamadas a los métodos para realizar las distintas acciones se llevan a cabo separando los
identificadores de la referencia y del método correspondiente con el operador punto:
(idReferencia.idMetodo(parametros))

El siguiente código muestra la declaración de la clase Precio. La clase Precio consta de un


único atributo (euro) y dos métodos: uno que asigna un valor al atributo (pone) sin
devolver ningún valor y otro que devuelve el valor del atributo (da).

03- Programación Orientada a Objetos Página 12


Lenguaje de Programación II Prof. Melvyn Quiñones
/**
* Ejemplo de declaracion de la clase Precio
* double da() --> devuelve el valor almacenado en euros
* void pone( double x ) --> almacena valor en euros
*/
public class Precio {
// Atributo o variable miembro
public double euros;

// Metodos
public double da() {
return this.euros;
}
public void pone(double x) {
this.euros = x;
}
}
Gráficamente, una clase puede representarse como un rectángulo, tal y como se muestra
la representación gráfica de la clase Precio:

El anterior código puede compilarse:


$>javac Precio.java

generando el archivo de bytecodes Precio.class. Este archivo no es directamente


ejecutable por el intérprete, ya que el código fuente no incluye ningún método principal
(main). Para poder probar el código anterior, puede construirse otro archivo con el código
fuente que se muestra a continuación:
/**
* Ejemplo de uso de la clase Precio
*/
public class PruebaPrecio {
public static void main (String []args ) {
Precio p; // Crea una referencia de la clase Precio
p = new Precio(); // Crea el objeto de la clase Precio
p.pone(56.8); // Llamada al metodo pone
// que asigna 56.8 al atributo euros
// Llamada al metodo da que devuelve el valor de euros
System.out.println("Valor = " + p.da());
Precio q = new Precio(); // Crea una referencia y el objeto
q.euros=75.6; // Asigna 75.6 al atributo euros
System.out.println("Valor = " + q.euros);
}
}

03- Programación Orientada a Objetos Página 13


Lenguaje de Programación II Prof. Melvyn Quiñones

A continuación, Representación gráfica del espacio de la memoria utilizado por las


referencias e instancias de la clase Precio durante la ejecución del método main de la clase
“PruebaPrecio”:

Para poder trabajar con objetos se tendrá que seguir un proceso de dos pasos. Lo primero
que debe hacer el programa es crear una referencia o puntero de la clase Precio con el
identificador p. De forma similar a cómo se declara una variable de un tipo primitivo, la
declaración del identificador de la referencia se realiza con la sintaxis:

identificadorClase identificadorReferencia;
// En el ejemplo anterior: Precio p;
A continuación, la grafica de la creación de la referencia p:

La referencia o puntero, p, tiene como misión almacenar la dirección de memoria de


(apuntar a) los componentes de la instancia que todavía no ha sido creada ni referenciada.
En este momento se dice que la referencia p, recién creada, almacena una dirección de
memoria nula (que no corresponde a objeto alguno) o null. El segundo paso del proceso
para trabajar con objetos lleva a la creación de una nueva instancia referenciada por p,
que se realiza con la sentencia:

Creación de la nueva instancia de la clase Precio referenciado por p

A esta operación se le denomina también instanciación. Aunque las dos operaciones


anteriores (creación de la referencia y creación de la instancia referenciada) pueden
realizarse conjuntamente en la misma línea de código:
identificadorClase identificadorReferencia = new identificadorClase();
// En el codigo del ejemplo anterior: Precio q = new Precio();

Creación de la referencia q y de la nueva instancia de la clase Precio referenciado por q:

03- Programación Orientada a Objetos Página 14


Lenguaje de Programación II Prof. Melvyn Quiñones

El resultado de la ejecución del código anterior son dos nuevas instancias de la clase
Precio referenciados respectivamente por p y q. El atributo euros de cada una de las
nuevas instancias de la clase Precio es accesible a través del identificador de la referencia
y del operador punto (p.euros y q.euros). Los métodos da y pone pertenecientes a la clase
Precio son accesibles a través del identificador de la referencia y del operador punto
(p.da() y p.pone(56.8) y q.da() y q.pone(75.6), respectivamente). En el caso de los
métodos, la instancia mediante la cual se realiza la llamada correspondiente actúa como
un parámetro o argumento implícito del método.

Si se asigna una referencia a otra mediante una sentencia de asignación, no se copian los
valores de los atributos, sino que se tiene como resultado una única instancia apuntada
por dos referencias distintas. Por ejemplo:
q = p; // Ahora p y q referencian al mismo objeto

En este caso ¿qué ocurre con la instancia referenciada previamente por q? Dicha instancia
se queda sin referencia (inaccesible). Esto puede ser un problema en algunos lenguajes de
programación, como es el caso de Pascal o de C, que utilizan variables dinámicas y que
necesitan liberar explícitamente el espacio en memoria reservado para las variables que
van a dejar de ser referenciadas. La gestión dinámica de la memoria suele ser una tarea
engorrosa para el programador y muy dada a la proliferación de errores de ejecución. Para
evitar tales inconvenientes, Java permite crear tantas instancias como se desee (con la
única limitación de la memoria que sea capaz de gestionar el sistema), sin que el
programador tenga que preocuparse de destruirlas o liberarlas cuando ya no se necesiten.
El entorno de ejecución de Java elimina automáticamente las instancias cuando detecta
que no se van a usar más (cuando dejan de estar referenciadas). A este proceso se le
denomina recogida o recolección de basura (garbage collection).

El operador instanceof

El operador instanceof devuelve verdadero o falso si un objeto pertenece o no a una clase


determinada. Sintaxis:
identificadorInstancia instanceof identificadorClase

No podemos usar instanceof para tratar de comprobar dos clases de diferentes jerarquías.
Por ejemplo, NO podemos hacer la comparación con un objeto hijo de la clase Math con
un hijo de la clase String. Esto provocaría un error de compilación.

03- Programación Orientada a Objetos Página 15


Lenguaje de Programación II Prof. Melvyn Quiñones

3. Modificadores de Acceso
Como su nombre indica, los modificadores de acceso en Java ayudan a restringir el alcance
de una clase, constructor, variable, método o miembro de datos. Hay cuatro tipos de
modificadores de acceso disponibles en Java:

 Default – No se requiere palabra clave


 Private
 Protected
 Public

Modificador de acceso por defecto (default)

Cuando no se especifica ningún modificador de acceso para una clase, método o miembro
de datos, se dice estar teniendo modificador de acceso default por defecto.

Los miembros de datos, clase o métodos que no se declaran utilizando ningún modificador
de acceso, es decir, que tengan un modificador de acceso predeterminado, solo son
accesibles dentro del mismo paquete.

En este ejemplo, crearemos dos paquetes y las clases en los paquetes tendrán los
modificadores de acceso predeterminados e intentaremos acceder a una clase de un
paquete desde otra clase del segundo paquete.

// Programa Java para ilustrar el modificador default


package p1;

// La clase DemoDefault tiene modificador de acceso default


class DemoDefault {
void mostrar()
{
System.out.println("Hola Mundo!");
}
}

03- Programación Orientada a Objetos Página 16


Lenguaje de Programación II Prof. Melvyn Quiñones
// Programa Java para ilustrar el error
// al usar la clase de un paquete diferente con
// modificador default
package p2;
import p1.*;

// Esta clase tiene un modificador de acceso predeterminado


public class DemoDefaultEjecutar {
public static void main(String args[])
{
//accessing class Geek from package p1
DemoDefault obj = new DemoDefault();
obj.mostrar();
}
}
Salida:
Error:(12, 9) java: cannot find symbol
symbol: class DemoDefault
location: class p2.DemoDefaultEjecutar

Modificador de acceso privado (private)

El modificador de acceso privado se especifica con la palabra clave private. Los métodos o
los miembros de datos declarados como privados solo son accesibles dentro de la clase en
la que se declaran. Cualquier otra clase del mismo paquete no podrá acceder a estos
miembros. Las clases e interfaces no se pueden declarar como privadas (private).

En este ejemplo, crearemos dos clases A y B dentro del mismo paquete p1. Declararemos
un método en la clase A como privado e intentaremos acceder a este método desde la
clase B y veremos el resultado.

// Programa Java para ilustrar el error


// al usar la clase desde un mismo paquete
// con modificador private
package p1;

class A {
private void mostrar() {
System.out.println("Java desde Cero");
}
}
class B{
public static void main(String[] args) {
A obj= new A();
//tratando de acceder al método privado de otra clase
obj.mostrar();
}
}
Salida:
Error:(15, 12) java: mostrar() has private access in p1.A

03- Programación Orientada a Objetos Página 17


Lenguaje de Programación II Prof. Melvyn Quiñones

Modificador de acceso protegido (protected)

El modificador de acceso protegido se especifica con la palabra clave protected. Los


métodos o miembros de datos declarados como protected son accesibles dentro del
mismo paquete o sub-clases en paquetes diferentes.

En este ejemplo, crearemos dos paquetes p1 y p2. La clase A en p1 es public, para acceder
a ella desde p2. El método que se muestra en la clase A está protegido y la clase B se
hereda de la clase A y, a continuación, se accede a este método protegido creando un
objeto de clase B.
// Programa Java para ilustrar
// el modificador protected
package p1;

public class A {

protected void mostrar(){


System.out.println("Dios te bendiga");
}

// Programa Java para ilustrar


// el modificador protected
package p2;

// importar todas las clases en el paquete p1


import p1.*;

public class B extends A {


public static void main(String[] args) {
B obj = new B();
obj.mostrar();
}
}
Salida:
Dios te bendiga

Modificador de acceso público (public)

El modificador de acceso público se especifica con la palabra clave public.

El modificador de acceso público tiene el alcance más amplio entre todos los demás
modificadores de acceso.

03- Programación Orientada a Objetos Página 18


Lenguaje de Programación II Prof. Melvyn Quiñones

Las clases, métodos o miembros de datos que se declaran como públicos son accesibles
desde cualquier lugar del programa. No hay restricciones en el alcance de los miembros
de datos públicos.

// Programa Java para ilustrar


// el modificador public
package p1;

public class A {
public void mostrar(){
System.out.println("Dios te bendiga");
}
}

// Programa Java para ilustrar


// el modificador protected
package p2;

// importar todas las clases en el paquete p1


import p1.*;

public class B extends A {


public static void main(String[] args) {
A obj = new A();
obj.mostrar();
}
}
Salida:
Dios te bendiga

Modificadores que no son de acceso

En Java, tenemos 7 modificadores que no son de acceso o, a veces, también llamados


especificadores. Se usan con clases, métodos, variables, constructores, etc. para
proporcionar información sobre su comportamiento a la JVM. Y son:
 static
 final
 abstract
 synchronized
 transient
 volatile
 native

Algunos de estos los iremos viendo en el transcurso.

03- Programación Orientada a Objetos Página 19


Lenguaje de Programación II Prof. Melvyn Quiñones

4. Tipos de atributos
Los atributos, también llamados “datos o variables miembro” son porciones de
información que un objeto posee o conoce de sí mismo. Una clase puede tener cualquier
número de atributos o no tener ninguno. Se declaran con un identificador y el tipo de dato
correspondiente. Además los atributos, tienen asociado un modificador que define su
visibilidad según se muestra en la siguiente tabla.

Modificadores y visibilidad correspondiente:

Variables de instancia

Cuando se declara el atributo o variable miembro euros en la clase Precio de la siguiente


forma:
public class Precio {

// Declaracion de atributos o variables miembro
public double euros;


// Declaracion de metodos . . .
}

Se está declarando el atributo euros como una variable de instancia. En consecuencia,


cada vez que se crea una instancia de la clase Precio, se reserva espacio en memoria para
una variable de instancia euros. Por ejemplo, el código:
// Creacion de dos instancias de la clase precio
Precio p = new Precio();

p.pone(56.8);

Precio q = new Precio();
q.pone(75.6);

Genera dos instancias de la clase Precio como muestra la figura siguiente. En este caso,
cada una de las dos instancias, p y q, de la clase Precio tiene una variable de instancia
euros propia. Las respectivas llamadas al método pone para cada instancia
(p.pone(56.8) y q.pone(75.6)), permiten asignar un valor a las variables de instancia
correspondientes.

03- Programación Orientada a Objetos Página 20


Lenguaje de Programación II Prof. Melvyn Quiñones

Otro ejemplo. En la declaración de la clase Fecha se incluyen tres atributos (dia, mes y
anho) que son variables de instancia:
public class Fecha {
// Declaracion de atributos o variables miembro
private int dia;
private int mes;
private int anho;

// Declaracion de metodos . . .
}

Con el siguiente código se crean dos instancias de la clase Fecha:


// Creacion de dos instancias de la clase Fecha
Fecha a = new Fecha();
Fecha b = new Fecha();

Cada una de las instancias de la clase Fecha reserva espacio en memoria para cada una de
las variables de instancia como muestra la siguiente figura:

Las variables de instancia pueden declararse como public o como private y pueden
pertenecer a cualquiera de los tipos de datos primitivos de Java o bien, a otra clase
existente en Java o declarada por el usuario. En principio, la única limitación para el
número de variables de instancia que puede declarar una clase es el espacio libre
disponible en la memoria del sistema que ejecute el programa.

Variables de clase (static)

Las variables de clase son atributos diferentes de las variables de instancia. Las variables
de clase implican una sola zona de memoria reservada para todas las instancias de la
clase, y no una copia por objeto, como sucede con las variables de instancia. Para
diferenciarlas de éstas en el código fuente de Java, las variables de clase se distinguen con
el modificador static en la declaración del atributo correspondiente. Por defecto (si no se
indica la palabra static), el atributo declarado se considera variable de instancia.

Durante la ejecución del programa, el sistema reserva un único espacio en memoria para
cada variable estáticas o de clase independientemente del número de instancias creadas
de una clase. Esta reserva se produce la primera vez que encuentra dicha clase en el
código, de forma que todas las instancias pertenecientes a una clase comparten la misma
variable de clase. A diferencias de las variables globales fuera de la POO, las variables de
clase garantizan la encapsulación.

03- Programación Orientada a Objetos Página 21


Lenguaje de Programación II Prof. Melvyn Quiñones

Las variables de clase sirven para almacenar características comunes (constantes) a todos
los objetos (número de ruedas de una bicicleta) o para almacenar características que
dependen de todos los objetos (número total de billetes de lotería). Por ejemplo, la clase
CuentaBancaria tiene una variable de instancia, saldo, y una variable de clase,
totalCuentas.
public class CuentaBancaria {
// Atributos o variables miembro
public double saldo; // Variable de instancia
public static int totalCuentas=0; // Variable de clase
// Declaraciones de metodos...
}

La creación de varias instancias de la clase CuentaBancaria no conlleva la existencia de


varias variables totalCuentas. Durante la ejecución de un programa que utilice la clase
CuentaBancaria sólo existirá una variable de clase totalCuentas, independientemente del
número de instancias de la clase CuentaBancaria que se generen. Es más, no es necesario
siquiera que exista una instancia de la clase, para que lo haga la variable de clase. De
hecho, se inicializan a false, cero o null (dependiendo de su tipo) antes de que se genere
una instancia de la clase.
// Creacion de dos instancias de la clase CuentaBancaria
CuentaBancaria c1 = new CuentaBancaria();
CuentaBancaria c2 = new CuentaBancaria();

Las variables de clase se emplean cuando sólo es necesaria una copia por clase que,
además, esté accesible por todas las instancias de la clase a la que pertenece. En este
caso, al ser un atributo public y static, puede accederse directamente a la variable de clase
(totalCuentas) a través de una instancia (c1 o c2) o de la clase en sí (CuentaBancaria). Un
atributo estático puede ser accedido desde cualquier instancia de la clase, ya que es
miembro de la propia clase.
public class PruebaCuentaBancaria {

public static void main (String [] args) {
CuentaBancaria c1 = new CuentaBancaria();
c1.totalCuentas++;
System.out.println("Total cuentas: " + c1.totalCuentas);
CuentaBancaria c2 = new CuentaBancaria();
c2.totalCuentas++;

System.out.println("Total cuentas: " + c2.totalCuentas);
// Acceso a traves de la clase:
CuentaBancaria.totalCuentas++;
System.out.println("Total cuentas: " +
CuentaBancaria.totalCuentas);
}
}

03- Programación Orientada a Objetos Página 22


Lenguaje de Programación II Prof. Melvyn Quiñones

La ejecución del código anterior origina la siguiente salida por pantalla:


$>java PruebaCuentaBancaria
Total cuentas: 1
Total cuentas: 2
Total cuentas: 3

Para operar con variables de clase también podemos implementar métodos en la clase.
Por ejemplo el siguiente método incTotalCuentas incrementa en una unidad el valor de la
variable de clase totalCuentas.
public static void incTotalCuentas() {
totalCuentas++;
}

Al ser declarado el método incTotalCuentas como un método public y static, puede


llamarse mediante cualquiera de las instancias (c1 o c2) o de la clase en sí
(CuentaBancaria).

Las variables de clase pueden declararse como public o como private y pueden pertenecer
a cualquiera de los tipos de datos primitivos de Java o bien, a otra clase existente en Java
o declarada por el usuario. En principio, la única limitación para el número de variables de
clase que puede declarar una clase es el espacio libre disponible por el sistema que
ejecute el programa.

Constantes o variables finales (final)

Una clase puede contener atributos de valor constante o variables finales. Este tipo de
atributo se indica con la palabra reservada final. Las variables finales se suelen declarar
además como variables de clase (static final) por razones de ahorro de memoria ya que, al
no modificar su valor sólo suele ser necesaria una copia en memoria por clase (y no una
por instancia). Por ejemplo, en la clase Circulo:
public class Circulo {

// Atributos o variables miembro

private static final double PI = 3.141592; // Constante de
clase
private double radio;


// Declaracion de metodos ...



}

La palabra reservada final indica que el atributo debe comportarse como una constante,
es decir, no puede ser modificada una vez declarada e inicializada. Por otro lado, se puede
separar la declaración de la inicialización de la variable final, realizándose ésta más tarde.
En este caso, el valor asignado a la variable final puede hacerse en función de otros datos
o de llamadas a métodos, con lo que el valor de la constante no tiene porqué ser el mismo
para diferentes ejecuciones del programa.
03- Programación Orientada a Objetos Página 23
Lenguaje de Programación II Prof. Melvyn Quiñones

5. Clases estándar de java


Uno de los puntos fuertes de Java es la gran cantidad de clases predefinidas que posee.
Dichas clases pueden ser utilizadas por los programadores sin necesidad de reinventar la
rueda. En este capítulo se presentan algunas de las clases predefinidas de Java que se
suelen utilizar más en la construcción de programas.

Clases contenedoras o Wrappers

En Java existen una serie de clases predefinidas equivalentes a los tipos primitivos
denominadas wrappers, clases contenedoras o envoltorios. Como muestra la siguiente
tabla el identificador de cada una de estas clases es el mismo que el del tipo primitivo
correspondiente pero con la letra inicial en mayúsculas (salvo int - Integer y char -
Character). Cada una de estas clases declaran un conjunto de métodos de gran utilidad.

El uso de estas clases puede ser especialmente interesante para realizar determinadas
operaciones mediante los métodos que implementan. En la siguiente sección se analiza el
uso de la clase Character.

Objetos de la clase Character

La clase predefinida Character permite trabajar con instancias a las que se les puede
asociar un único carácter Unicode. Esta clase incluye un conjunto de métodos que facilitan
la manipulación de datos de tipo primitivo char.

03- Programación Orientada a Objetos Página 24


Lenguaje de Programación II Prof. Melvyn Quiñones

El siguiente código muestra cómo crear referencias e instancias de la clase Character:

Character a1;?
a1 = new Character('A');
Character a2 = new Character('B');

Otro método de la clase Character:

Objetos de la clase String

String es una clase predefinida y especial de Java definida en la librería o paquete java.lang
y orientada a manejar cadenas constantes de caracteres. Una instancia de la clase String
es inmutable, es decir, una vez que se ha creado y se le ha asignado un valor, éste no
puede modificarse (añadiendo, eliminando o cambiando caracteres). El siguiente código
muestra diferentes ejemplos de creación de referencias e instancias de la clase String:
String cortesia = new String("Buenos dias");?
// O bien, al ser una clase muy habitual en la forma abreviada:
String saludo = "Hola";?
// O tambien:?
String despedida;?
despedida = "Adios";

Como se ha visto anteriormente, las constantes de la clase String o cadenas literales se


indican entre comillas dobles. Estas comillas no se consideran parte de la cadena.

Operaciones con instancias de la clase String

Al ser un objeto, una instancia de la clase String no sigue las normas de manipulación de
los datos de tipo primitivo con excepción del operador concatenación. El operador +
realiza una concatenación cuando, al menos, un operando es un String. El otro operando
puede ser de un tipo primitivo. El resultado es una nueva instancia de tipo String. Por
ejemplo:
"casa" + "blanca" // Genera "casablanca"
"capitulo" + 5 // Genera "indice5"
5 + "capitulo" // Genera "5capitulo"
"x" + 2 + 3 // Genera "x23"
2 + 3 + "x" // Genera "5x": cuidado con la prioridad de los
operadores
2 + (3 + "x") // Genera "23x"

03- Programación Orientada a Objetos Página 25


Lenguaje de Programación II Prof. Melvyn Quiñones

También puede emplearse el operador +=, de forma que la sentencia a+=b es equivalente
a la sentencia a = a+b.

La comparación de dos objetos String no se realiza con el operador igualdad (==), ya que
se compararían las referencias, sino que se realiza con el método equals, de forma que
cadena1.equals(cadena2) devuelve true si cadena1 y cadena2 hacen referencia a un
mismo valor. Los métodos más importantes de la clase String se resumen en la siguiente
tabla:

Para visualizar por pantalla el contenido de un objeto String pueden emplearse los
métodos print y println de la clase estándar System.out.
if (saludo.equals(despedida))
System.out.println(saludo);
else
System.out.println(despedida);

La longitud de una cadena puede obtenerse con el método length perteneciente a la clase
String que devuelve un valor entero que indica el número de caracteres que componen la
cadena:
String despedida = "Adios";?
int longitud = despedida.length(); // longitud toma el valor 5
longitud = "Hasta luego".length(); // longitud toma el valor 11

Una cadena de longitud igual a 0, que no contiene ningún carácter, se denomina cadena
vacía y se representa como "". Por otro lado, el método charAt devuelve el carácter cuya
posición indica el parámetro de la llamada, teniendo en cuenta que las posiciones se
indican con valores enteros y que el 0 corresponde al primer carácter de la cadena.
char c = despedida.charAt(2); // c toma el valor 'i'

03- Programación Orientada a Objetos Página 26


Lenguaje de Programación II Prof. Melvyn Quiñones

Otros métodos para trabajar con objetos de la clase String

El método substring, con los parámetros enteros inicio y fin, devuelve una nueva
subcadena contenida en la de origen. Si sólo se le indica el primer parámetro, devuelve la
cadena a partir del carácter indicado hasta el final de la cadena original. Por ejemplo:
String despedida = "Adios";
?String s1 = despedida.substring(1,3); // s1 toma el valor "di"
String s2 = despedida.substring(1); // s2 toma el valor "dios"

El listado compelto de métodos disponibles para la clase String, puede encontrarse en la


API oficial de Java http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

Clase Array

Otra clase estándar muy empleada en Java es la clase array o vector. El término español
vector para referirse a esta clase de objetos puede dar lugar a confusión ya que, como se
verá más adelante, existe una clase Vector predefinida en Java. En este caso y sin que sirva
de precedente, es conveniente emplear el término inglés array.

Objetos de la clase Array

Un objeto de la clase predefinida array permite representar una secuencia lineal y finita
de elementos del mismo tipo. Estos elementos pueden ser de tipo primitivo o
pertenecientes a otras clases. Los arrays son objetos con características propias. Además
del conjunto de elementos del mismo tipo, un objeto de tipo array almacena en memoria
una constante numérica entera que representa el número de elementos o tamaño del
array.

La declaración de un puntero o referencia a un array se lleva a cabo de la siguiente


manera:
tipoElemento [] identificadorInstancia;

Por ejemplo, la declaración de un puntero o referencia a un array de números enteros:


int [] p; // se declara el puntero o referencia del array de enteros

Como ocurre con los demás objetos, la ejecución de la sentencia anterior sólo crea la
referencia del array, pero no el array en sí.

En la declaración del identificador de la variable tampoco se especifica el tamaño del array


a referenciar. El tamaño del array se declara y establece cuando se crea la instancia array.

03- Programación Orientada a Objetos Página 27


Lenguaje de Programación II Prof. Melvyn Quiñones

La creación de un vector o array, una vez declarado su referencia se hace de la siguiente


forma:
identificadorInstancia = new tipoElemento [numeroElementos];
Por ejemplo:
p = new int [5]; // se crea el array de 5 enteros referenciado por p

De esta manera, se reserva espacio para todos los elementos del array: 5 valores enteros.

La creación de una referencia/puntero y del array de enteros al que apunta puede llevarse
a cabo de forma simultánea en la misma sentencia:

int [] p = new int [5]; // se declara el puntero y se crea el vector

Operaciones con Arrays

Puede accederse al tamaño en el código fuente del programa mediante el atributo length
que devuelve el número de elementos de un array (identificadorArray.length).

El acceso a cada elemento del array se realiza con el identificador de la instancia, la pareja
de corchetes y su índice (un valor numérico entero), considerando que el primer elemento
tiene índice 0:

// Al primer elemento del array se le asigna el valor -15


p[0] = -15;
// Al segundo elemento del array se le asigna el valor 26
p[1] = 26;
// Al tercer elemento del array se le asigna el valor 34
p[2] = 34;

Por lo tanto, a un array de n elementos le corresponde siempre un índice válido dentro del
intervalo [0 ... n-1]. Un error muy común es intentar acceder al elemento de índice n, que

03- Programación Orientada a Objetos Página 28


Lenguaje de Programación II Prof. Melvyn Quiñones

no existe (se producirá un error de ejecución out of bounds). Para especificar el índice de
un elemento pueden emplearse tanto constantes como variables de tipo entero.

Otro error es tratar de emplear el identificador del array como si fuera un dato de tipo
primitivo. Por ejemplo, la sentencia
p = p + 34;

generará un error de compilación.

Se suelen emplear bucles cuando se quiere trabajar con todos los elementos de un array.
El siguiente ejemplo muestra como trabajar con todos los elementos de dos arrays de
números (uno de valores enteros y otro de valores reales). El segundo de ellos almacena la
raiz cuadrada de los valores almacenados en el primero:
/**?
* ArrayRaices: Ejemplo de uso de arrays
*/
public class ArrayRaices {?
public static void main (String [] args ) {
int [] numero = new int[10]; // Array de valores enteros
double [] raiz = new double[10]; // Array de valores reales

for (int i=0; i<numero.length; i++) {


numero[i] = i+1;?
raiz[i] = Math.sqrt(numero[i]);
System.out.println(numero[i] + " : " + raiz[i]);
}
}
}

Es importante ver que el bucle for emplea la expresión i<numero.length como condición
de término.

También puede llevarse a cabo la declaración e inicialización simultánea de un array (con


los valores correspondientes separados por comas y entre llaves) en la misma sentencia
de código. Por ejemplo:
double [] x = {1.5, 2.3, -0.6, 4.8};

Este tipo de inicialización sólo es válida en la sentencia de declaración de la referencia del


array. El resultado de la ejecución de la sentencia anterior se muestra en la siguiente
figura:

03- Programación Orientada a Objetos Página 29


Lenguaje de Programación II Prof. Melvyn Quiñones

Array de objetos

El uso de vectores no tiene por qué restringirse a elementos de tipo primitivo. Por
ejemplo, pueden crearse sendas referencias a arrays de referencias de la clase precio (tal y
como se declaró esta clase en un ejemplo anterior) o de la clase String:
precio [] catalogo; catalogo = new precio [5]; catalogo[0] = new
precio();
// Creacion de la referencia?// Creación del array de referencias?//
Creación del primer elemento/instancia precio

El resultado de la ejecución de las sentencias anteriores se muestra en la siguiente figura.


Primero se crea la referencia al array de punteros, luego se crea el array de punteros y,
finalmente, se crea la instancia de la clase precio y se almacena su dirección de memoria
en el primer elemento del array de punteros.

En el caso de trabajar con un array de String, se emplean las siguientes sentencias:


String [] Tabla; // Creacion de la referencia?
Tabla = new String [10]; // Creación del array de referencias?
Tabla[0] = new String(); // Creación del primer elemento/instancia
String
En el siguiente código se muestra un ejemplo de cómo trabajar con el array de objetos de
la clase precio:
/**
* ArrayPrecios: Ejemplo de uso de arrays de objetos
*/
public class ArrayPrecios {?
public static void main (String [] args) {
Precio [] catalogo; // Creacion de la referencia?
catalogo = new Precio [5]; // Creacion array de referencias precio

for (int i=0; i<catalogo.length; i++) {?


catalogo[i] = new precio(); // Creacion del elemento i-esimo
catalogo[i].pone(10*Math.random());
System.out.println("Producto "+ i + " : " + catalogo[i].da());
}
// Busqueda del maximo precio?
double maximo=catalogo[0].da();?
for (int i=1; i<catalogo.length; i++) {
if (maximo<catalogo[i].da())
maximo=catalogo[i].da();
}
?System.out.println("El mas caro vale "+ maximo +" euros");
}
}

03- Programación Orientada a Objetos Página 30


Lenguaje de Programación II Prof. Melvyn Quiñones

Arrays multidimensionales
En Java también se puede trabajar con arrays multidimensionales, llamados comúnmente
matrices. Por ejemplo, la declaración de un puntero a una matriz bidimensional de números
enteros se puede realizar de la siguiente manera incluyendo un par de corchetes adicionales en la
declaración de la referencia:

La creación de la matriz (una vez declarado su puntero) puede hacerse según muestra la
siguiente sentencia:
m = new int [5][4]; // Crea una matriz para almacenar 5 x 4 enteros

En este caso se indican en el par de cochetes adicional el número de elementos según la


segunda dimensión. El resultado de la ejecución de la sentencia anterior se muestra en la
siguiente figura.

La ejecución del código anterior reserva espacio en memoria durante la ejecución del
programa para una matriz de 5 x 8 valores numéricos enteros. En realidad se reserva
espacio en memoria para un array de cinco punteros que, a su vez, almacenan la dirección
de memoria de otros tantos arrays de cuatro números enteros. Para referenciar a cada
uno de los elementos de los arrays de enteros es necesario utilizar el identificador del
puntero seguido de los correspondientes índices entre corchetes. Por ejemplo, como en
las siguientes sentencias:
m[0][0] = 34;
m[0][1] = 46;
m[0][2] = 13;
m[0][3] = -8;
m[1][0] = 5;
m[1][1] = 56;
m[1][2] = -3;

03- Programación Orientada a Objetos Página 31


Lenguaje de Programación II Prof. Melvyn Quiñones

Por otro lado, también puede llevarse a cabo la declaración de la referencia, creación del
array multidimensional e inicialización simultánea de sus elementos. Por ejemplo, la
siguiente sentencia genera una matriz 2 x 3 de números enteros:
// Matriz de dos filas y tres columnas?
int [][] a = { {1, 2, 3}, {4, 5, 6} };?
// Por ejemplo, el elemento a[1][0] contiene el valor 4
Creación de un array bidimensional de 2 x 3 números enteros e inicialización de sus
elementos:

El número de elementos de los arrays referenciados puede especificarse para cada uno de
ellos y ser diferente entre sí. Por ejemplo, la ejecución de la sentencia:
int [][] b = { {1, 2, 3}, {4, 5, 6, 7}, {8, 9} };

genera la estructura de datos representada en la siguiente figura. En dicha estructura no


existen, por ejemplo, los elementos b[0][3] ni b[2][2].
Creación de un array bidimensional no rectangular

En Java es posible trabajar con estructuras de tipo array con más de dos dimensiones
añadiendo simplemente los índices (y corchetes o llaves) que sean necesarios. Por
ejemplo, la siguiente sentencia crea una matriz tridimensional 2 x 2 x 3 de números
enteros:
int [][][] c = { { {1, 2, 3},{4, 5, 6} },{ {7, 8, 9}, {10, 11, 12} } }

El número de pares de corchetes en el término de la izquierda y de niveles de llaves en el


término de la derecha debe coincidir e indica el de dimensiones de la matriz. En principio,
en Java no hay límite para el número de dimensiones que pueden utilizarse en una matriz.

03- Programación Orientada a Objetos Página 32


Lenguaje de Programación II Prof. Melvyn Quiñones

6. Métodos en Java
Un método es un trozo de código que puede ser llamado o invocado por el programa
principal o por otro método para realizar alguna tarea específica. El término método en
Java es equivalente al de subprograma, rutina, subrutina, procedimiento o función en
otros lenguajes de programación. El método es llamado por su nombre o identificador
seguido por una secuencia de parámetros o argumentos (datos utilizados por el propio
método para sus cálculos) entre paréntesis. Cuando el método finaliza sus operaciones,
devuelve habitualmente un valor simple al programa que lo llama, que utiliza dicho valor
de la forma que le convenga. El tipo de dato devuelto por la sentencia return debe
coincidir con el tipo de dato declarado en la cabecera del método.

Sintaxis de declaración de un método:


[modificadores] TipoDeDato identificadorMetodo (parametros formales) {
declaraciones de variables locales;
sentencia_1;
sentencia_2;
...
sentencia_n;
// dentro de estas sentencias se incluye al menos un return
}

La primera línea de código corresponde a la cabecera del método. Los modificadores


especifican cómo puede llamarse al método, el tipo de dato indica el tipo de valor que
devuelve la llamada al método y los parámetros (entre paréntesis) introducen información
para la ejecución del método. Si no existen parámetros explícitos se dejan los paréntesis
vacíos. A continuación, las sentencias entre llaves componen el cuerpo del método.
Dentro del cuerpo del método se localiza, al menos, una sentencia return.

Seguidamente se muestra un ejemplo de declaración y uso de un método que devuelve el


cubo de un valor numérico real con una sentencia return:
/**
* Demostracion del metodo cubo
*/
public class PruebaCubo {
public static void main (String [] args){
System.out.println("El cubo de 7.5 es: " + cubo(7.5)); //
llamada
}
public static double cubo (double x) {
// declaracion
return x*x*x;
}
}
A diferencia de otros lenguajes de programación, como Pascal, en Java, la declaración del
método puede realizarse en el código fuente después de la llamada al propio método.

03- Programación Orientada a Objetos Página 33


Lenguaje de Programación II Prof. Melvyn Quiñones

En el caso anterior, public y static son los modificadores especificados en la cabecera del
método. El uso de estos dos modificadores permite que el tipo de método sea similar al de
una función global de Pascal o C. El identificador double hace referencia al tipo de dato
que devuelve la llamada al método, cubo es el identificador del método y x es el
identificador del parámetro en la declaración de la cabecera del método (parámetro
formal). Ejemplo de ejecución del código anterior y salida correspondiente por pantalla:
$>java PruebaCubo
El cubo de 7.5 es: 421.875

En Java, los métodos suelen ir asociados con los objetos o instancias en particular a los
que operan (métodos de instancia). Los métodos que no necesitan o trabajan con objetos
(y sí con números, por ejemplo) se denominan métodos estáticos o de clase y se declaran
con el modificador static. Los métodos estáticos o de clase son equivalentes a las rutinas
(funciones o procedimientos) de los lenguajes que no emplean la programación orientada
a objetos. Por ejemplo, el método sqrt de la clase Math es un método estático. También lo
es el método cubo del ejemplo anterior. Por otro lado, todo programa o aplicación Java
tiene un método principal main que será siempre un método estático.

¿Por qué se emplea la palabra static para los métodos de clase? El significado o la
acepción más común de la palabra estático (que permanece quieto en un lugar) parece no
tener nada que ver con lo que hacen los métodos estáticos. Java emplea la palabra static
porque C++ lo utiliza en el mismo contexto: para designar métodos de clase.
Aprovechando su empleo en variables que tienen una única localización en memoria para
diferentes llamadas a métodos, C++ lo empezó a utilizar en la designación de los métodos
de clase para diferenciarlos de los métodos de instancia y no confundir al compilador. El
problema es que nadie pensó en que el uso de la palabra static pudiera causar
confusiones humanas.

Return y Void

En algunas ocasiones, no es necesario que el método estático tenga que devolver un valor
al finalizar su ejecución. En este caso, el tipo de dato que debe indicar en la cabecera de
declaración del método es el tipo void y la sentencia return no viene seguida de ninguna
expresión.

Sintaxis:
return;

En el siguiente código se incluye un ejemplo de método que no devuelve un valor (de tipo
void):
/**
* Demostracion del metodo tabla

03- Programación Orientada a Objetos Página 34


Lenguaje de Programación II Prof. Melvyn Quiñones
*/
public class PruebaTabla {
public static void main (String [] args){
tabla(4);
tabla(7);
}
public static void tabla (int n) {
// ejemplo de llamada
// de tipo void
System.out.println("Tabla de multiplicar del numero " + n);
for (int i=0; i<=10; i++)
System.out.println(n + " x " + i + " = " + producto(n,i));

return; // No devuelve ningun valor


}
public static int producto (int a, int b) {
return a*b;
}
}

Si no hay sentencia return dentro de un método, su ejecución continúa hasta que se


alcanza el final del método y entonces se devuelve la secuencia de ejecución al lugar
dónde se invocó al método.

Un método cuyo tipo de retorno no es void necesita siempre devolver algo. Si el código de
un método contiene varias sentencias if debe asegurarse de que cada una de las posibles
opciones devuelve un valor. En caso contrario, se generaría un error de compilación.
Por ejemplo:
/**
* Demostracion de la funcion esPositivo
*/
public class PruebaPositivo {
public static void main (String [] args) {
for (int i=5; i>=-5; i--)
System.out.println(i + " es positivo: " + esPositivo(i));
}
public static boolean esPositivo(int x) {
if (x<0) return false;
if (x>0) return true;
// Error: retorno perdido si x es igual a cero.
}
}

Ejemplo de intento de compilación del código anterior:


$>javac PruebaPositivo.java
pruebaPositivo.java:14: missing return statement
}
^

03- Programación Orientada a Objetos Página 35


Lenguaje de Programación II Prof. Melvyn Quiñones

Recursión

Java permite la recursión o recurrencia en la programación de métodos. La recursión


consiste en que un método se llame a sí mismo. Un ejemplo muy típico de empleo de la
recursión puede verse en la construcción de un método que devuelva el factorial de un
entero. Se basa en el hecho de que n! es igual a n·(n-1)! si n es mayor que 1. Por ejemplo:

/**
* Demostracion de la funcion recursiva factorial
*/
public class PruebaFactorialR {
public static void main (String [] args){
for (int i=1; i<=20; i++)
System.out.println("Factorial de " + i + " = " + factorialR(i));
}
}
public static long factorialR (int n) {
if (n==0)
return 1;
else
return n * factorialR(n-1);
}
}
En la construcción de métodos recursivos es importante evitar el problema de la recursión
infinita. Es decir, que en algún caso, la ejecución del método definido de forma recursiva
no implique una nueva llamada al propio método.

Sobrecarga de métodos (Overload)

Java permite asignar el mismo identificador a distintos métodos, cuya diferencia reside en
el tipo o número de parámetros que utilicen. Esto resulta especialmente conveniente
cuando se desea llevar a cabo la misma tarea en difererente número o tipos de variables.
La sobrecarga (overloading) de los métodos puede resultar muy útil al efectuar llamadas a
un método, ya que en lugar de tener que recordar identificadores de métodos distintos,
basta con recordar uno sólo. El compilador se encarga de averiguar cuál de los métodos
que comparten identificador debe ejecutar. Por ejemplo:

/**
* Demostracion de metodos sobrecargados * A. Garcia-Beltran - marzo,
2002
*/
public class PruebaSobrecarga {
public static void main (String[] args) {
int a=34;

03- Programación Orientada a Objetos Página 36


Lenguaje de Programación II Prof. Melvyn Quiñones
int b=12;
int c=56;
System.out.println("a = " + a + "; b = " + b + "; c = " + c);
// El primer método
System.out.println("El mayor de a y b es: " + mayor(a,b));
// El segundo método
System.out.println("El mayor de a, b y c es: " +
mayor(a,b,c));
}
// Definicion de mayor de dos numeros enteros
public static int mayor (int x, int y) {
return x>y ? x : y;
}
// Definicion de mayor de tres numeros enteros
public static int mayor (int x, int y, int z) {
return mayor(mayor(x,y),z);
}
}
Ejemplo de salida por pantalla:
$>java PruebaSobrecarga
a = 34; b = 12; c = 56
El mayor de a y b es: 34 El mayor de a, b y c es: 56

Tipos de métodos

Un método es una abstracción de una operación que puede hacer o realizarse con un
objeto. Una clase puede declarar cualquier número de métodos que lleven a cabo
operaciones de lo más variado con los objetos.

En esta sección los métodos se clasifican en dos grupos: los métodos de instancia y los
métodos de clase.

Métodos de instancia

Las clases pueden incluir en su declaración muchos métodos o no declarar ninguno. Los
métodos pueden clasificarse en métodos de instancia y métodos de clase.

Los métodos de instancia operan sobre las variables de instancia de los objetos pero
también tienen acceso a las variables de clase. La sintaxis de llamada a un método de
instancia es:
// Llamada tipica a un metodo de instancia
idReferencia.idMetodo(parametros);

03- Programación Orientada a Objetos Página 37


Lenguaje de Programación II Prof. Melvyn Quiñones

Todas las instancias de una clase comparten la misma implementación para un método de
instancia. La instancia que hace la llamada al método es siempre un parámetro o
argumento implícito. Dentro de un método de instancia, el identificador de una variable
de instancia hace referencia al atributo de la instancia concreta que hace la llamada al
método (suponiendo que el identificador del atributo no ha sido ocultado por el de un
parámetro).

En el ejemplo anterior en la declaración de la clase CuentaBancaria, los métodos saldo y


transferencia son métodos de instancia.
public double saldo() {
return this.saldo;
}
public void transferencia( CuentaBancaria origen ) {
this.saldo += origen.saldo;
origen.saldo = 0;
}

Ejemplos de llamada a estos métodos dentro de PruebaCuentaBancaria:


CuentaBancaria c1 = new CuentaBancaria();
CuentaBancaria c2 = new CuentaBancaria(20.0);
c1.transferencia(c2);
System.out.println("Cuenta con: " + c1.saldo() + " euros");

Métodos de clase

En principio, los métodos de clase no operan sobre las variables de instancia de los
objetos. Los métodos de clase pueden trabajar con las variables de clase pero no pueden
acceder a las variables de instancia declaradas dentro de la clase, a no ser que se crea una
nueva instancia y se acceda a las variables de instancia a través del nuevo objeto. Los
métodos de clase también pueden ser llamados precediéndolos con el identificador de la
clase, sin necesidad de utilizar el de una instancia.

IdClase.idMetodo(parametros); // Llamada tipica a un metodo de clase

La palabra static determina la declaración de un método de clase. Por defecto, si no se


indica la palabra static, el método declarado se considera un método de instancia.

En el ejemplo anterior en la declaración de la clase CuentaBancaria, el método incCuentas


es un método de clase.

public static void incCuentas () {


totalCuentas++;
}
Un ejemplo de llamada a este método dentro de PruebaCuentaBancaria sería:
CuentaBancaria.incCuentas();

03- Programación Orientada a Objetos Página 38


Lenguaje de Programación II Prof. Melvyn Quiñones

Las diferencias entre los métodos de instancia y los de clase se resumen aquí:

Los métodos de clase o estáticos se considerar equivalentes a las rutinas (globales) de


otros lenguajes de programación. Como ejemplos típicos de métodos estáticos pueden
indicarse los métodos de Java correspondientes a las funciones matemáticas sin, cos, exp,
pow... de la clase java.lang.Math. Las llamadas a estos métodos se realizan anteponiendo
el identificador de la clase Math al identificador del método: Math.sin(angulo)

03- Programación Orientada a Objetos Página 39


Lenguaje de Programación II Prof. Melvyn Quiñones

7. Parámetros o argumentos
Los parámetros o argumentos son una forma de intercambiar información con el método.
Pueden servir para introducir datos para ejecutar el método (entrada) o para obtener o
modificar datos tras su ejecución (salida).

Declaración de parámetros

Los parámetros se declaran en la cabecera de la declaración de los métodos. Al declararse


el parámetro, se indica el tipo de dato y el identificador correspondiente. Los parámetros
o argumentos de un constructor o de un método pueden ser de cualquier tipo, ya sean
tipos primitivos o referencias de objetos (en este caso debe indicarse el identificador de la
clase correspondiente). Ejemplos de declaraciones de cabeceras de métodos:

// Sin parametros
public double devuelve() {
return ...;
}
// Un parametro, x de tipo double
public void asigna(double x) {
...
}
// Dos parametros, a y b de tipo int
public int elMayor(int a, int b) {
...
}
// Un parametro, v, array real
public static double sumatorio (double [] v) {
...
}
// Un parámetro de la clase Fecha
public boolean caducado (Fecha fechaLimite) {
...
}
El identificador del parámetro se emplea sólo dentro del método para hacer referencia al
argumento correspondiente y puede coincidir con el de un atributo de la misma clase. En
tal caso, se dice que oculta a la variable miembro. Esta técnica suele emplearse en los
constructores para inicializar una instancia. Por ejemplo en la clase Circulo:
public class Circulo {
int x, y, radio;

public Circulo(int x, int y, int radio) {


...
}
}

03- Programación Orientada a Objetos Página 40


Lenguaje de Programación II Prof. Melvyn Quiñones

La clase Circulo tiene tres atributos o variables miembro x, y y radio y un constructor con
tres argumentos con los mismos identificadores que facilitan los valores iniciales a los
atributos respectivamente. Los identificadores de los parámetros ocultan a las variables
miembro dentro del cuerpo del constructor, de forma que x, y y radio dentro del
constructor hacen referencia a los parámetros y no a las variables miembro. Para acceder
a las variables miembro, es necesario emplear la palabra reservada this que referencia a la
instancia que está siendo inicializada por el constructor.
public class Circulo {
int x, y, radio;
public Circulo(int x, int y, int radio) {
this.x = x; // this.x hace referencia al atributo x
// x hace referencia al parametro x
this.y = y; // this.y hace referencia al atributo y
// y hace referencia al parametro y
this.radio = radio;
}
}
Normalmente dentro del cuerpo del método de una clase puede hacerse referencia
directa a las variables miembro de las instancias. Salvo en el caso del ejemplo anterior en
el que las variables miembro están ocultas. Por otro lado, los parámetros de un mismo
método no puede compartir el mismo identificador (no pueden coincidir) con el de una
variable local. El siguiente código genera un error de compilación:
public void asigna(double x) {
// Un parametro, x de tipo double
double x; // Error de compilacion
...
}

Uso alternativo de this como referencia al parámetro implícito

En la clase CuentaBancaria se implementa un método transferencia que transfiere el saldo


de una cuenta origen (parámetro formal explícito) a otra cuenta (parámetro implícito):

/**
* Declaracion de la clase CuentaBancaria
* Ejemplo de declaracion de variables
* metodos estaticos y uso de this
*/
public class CuentaBancaria {
// Atributos o variables miembro
private double saldo;
public static int totalCuentas=0;

// Metodos
public CuentaBancaria() {
this(0.0);

03- Programación Orientada a Objetos Página 41


Lenguaje de Programación II Prof. Melvyn Quiñones
}

public CuentaBancaria( double ingreso ) {


saldo = ingreso;
incCuentas();
}

public double saldo() {


return saldo;
}

public static void incCuentas () {


totalCuentas++;
}

// Transfiere todo el dinero de la cuenta origen a la actual


public void transferencia( CuentaBancaria origen ) {
saldo += origen.saldo;
origen.saldo=0;
}
}
Ejemplo de programa que emplea la clase CuentaBancaria con una llamada al método
transferencia:
/**
* Ejemplo de uso de la clase CuentaBancaria
*/
public class PruebaCuentaBancaria {
public static void main (String [] args) {
System.out.println("Total cuentas: " +
CuentaBancaria.totalCuentas);
CuentaBancaria c1;
c1 = new CuentaBancaria(17.5);

System.out.println("Nueva cuenta con: " + c1.saldo() + "


euros");
System.out.println("Total cuentas: " +
CuentaBancaria.totalCuentas);

CuentaBancaria c2;
c2 = new CuentaBancaria(20.0);
System.out.println("Nueva cuenta con: " + c2.saldo() + "
euros");
System.out.println("Total cuentas: " +
CuentaBancaria.totalCuentas);
System.out.println("Transferencia de cuenta 2 a cuenta 1");

c1.transferencia(c2);
System.out.println("Cuenta 1 con: " + c1.saldo() + " euros");
System.out.println("Cuenta 2 con: " + c2.saldo() + " euros");
}
}
La ejecución del código anterior origina la siguiente salida por pantalla:

03- Programación Orientada a Objetos Página 42


Lenguaje de Programación II Prof. Melvyn Quiñones
$>java PruebaCuentaBancaria
Total cuentas: 0
Nueva cuenta con: 17.5 euros
Total cuentas: 1
Nueva cuenta con: 20.0 euros
Total cuentas: 2
Transferencia de cuenta 2 a cuenta 1
Cuenta 1 con: 37.5 euros
Cuenta 2 con: 0.0 euros

En principio, el programa funciona correctamente, pero el código del método


transferencia puede dar lugar a que el saldo de las cuentas origen y destino se anule si
ambas son la misma cuenta (la llamada al método sería c1.transferenciaPeligrosa(c1);). Se
propone la siguiente modificación del código para que considere este caso (en el que no
se realiza ninguna operación con ningún saldo).

public void transferenciaSegura( CuentaBancaria origen ) {


// Test de verificacion: ¿destino igual a origen?
if ( this == origen )
return;

saldo += origen.saldo;
origen.saldo=0;
}

Paso por valor y paso por referencia

En Java todos los parámetros de los métodos se pasan por valor. Cuando se realiza la
llamada a un método, los parámetros formales (parámetros indicados en la declaración)
reservan un espacio en memoria independiente y reciben los valores de los parámetros
reales (parámetros indicados en la llamada al método). ¿Qué consecuencias tiene el paso
por valor de los parámetros?

Cuando el argumento es de tipo primitivo, el paso por valor significa que durante la
ejecución del método se reserva un nuevo espacio para el parámetro formal y no se
puede modificar el parámetro real durante la ejecución del método.

Cuando el argumento es de tipo referencia (por ejemplo, un array, un objeto,...) el paso


por valor significa que no puede modificarse la referencia pero se pueden realizar
llamadas a los métodos del objeto y modificar el valor asignado a las variables miembro
accesibles del objeto durante la ejecución del método.

Por ejemplo, en el siguiente programa el método cambiar utiliza un parámetro de tipo


primitivo (a, un valor numérico entero) y un parámetro de tipo referencia (b, un array de
valores enteros):

03- Programación Orientada a Objetos Página 43


Lenguaje de Programación II Prof. Melvyn Quiñones
/**
* Ejemplo de uso de parametros de distintos tipos
*/
public class Parametros {
public static void main (String [] args ) {
int n;
int [] v = new int[2];
n=10;
v[0]=20;
v[1]=30;

System.out.println("Antes: " + n + " " + v[0] +" "+ v[1]);


cambiar(n, v);
System.out.println("Después: " + n + " " + v[0] +" "+ v[1]);
}

public static void cambiar (int a, int [] b) {


a = 50;
b[0] = 60;
b[1] = 70;
System.out.println("Dentro: " + a + " " + b[0] +" "+ b[1]);
}
}
La ejecución del código anterior origina la siguiente salida por pantalla:
$>java Parametros
Antes: 10 20 30
Dentro: 50 60 70
Despues: 10 60 70

Esto es a menudo una fuente de errores: el programador escribe un método que trata de
modificar el valor de uno de sus parámetros y el método no funciona como esperaba.

Variables locales

En el cuerpo de un método pueden declararse variables adicionales que sólo pueden


emplearse dentro del propio método. Estas variables locales pueden ser de un tipo
primitivo o de un tipo referencia. Su existencia (reserva de espacio en memoria) sólo dura
mientras se está ejecutando la llamada al método.
public static double sumatorio (double [] v) {
int k; // Variable local entera
double x=0; // Variable local real
for (int k=0; k<v.length; k++)
x += v[k];

return x;
}
Una vez finalizada la ejecución del método, las variables locales k y x dejan de existir.

03- Programación Orientada a Objetos Página 44


Lenguaje de Programación II Prof. Melvyn Quiñones

8. Constructores
Aunque en un principio pueda parecer lo contrario, un constructor no es en realidad un
método estrictamente hablando. Un constructor es un elemento de una clase cuyo
identificador coincide con el de la clase correspondiente y que tiene por objetivo obligar a
y controlar cómo se inicializa una instancia de una determinada clase, ya que el lenguaje
Java no permite que las variables miembro de una nueva instancia queden sin inicializar.
Además, a diferencia de los métodos, los constructores sólo se emplean cuando se quiere
crear una nueva instancia.

Por defecto toda clase tiene un constructor sin parámetros cuyo identificador coincide con
el de la clase y que, al ejecutarse, inicializa el valor de cada atributo de la nueva instancia:
los atributos de tipo primitivo se inicializan a 0 o false, mientras que los atributos de tipo
objeto (referencia) se inicializan a null.

En el ejemplo de la clase PruebaPrecio, que utiliza una instancia de la clase Precio, la


llamada al constructor se produce en la sentencia p = new Precio();. Mientras que la
ejecución de new genera una nueva instancia y devuelve su dirección de memoria, la
ejecución del constructor Precio() inicializa los valores de los atributos.
public class PruebaPrecio {
public static void main(String [] args) {
Precio p; // Crea una referencia de la clase Precio
p = new Precio(); // Crea el objeto de la clase Precio y
realiza
// una llamada al metodo constructor
}
}

Declaración de un constructor

La declaración de un constructor diferente del constructor por defecto, obliga a que se le


asigne el mismo identificador que la clase y que no se indique de forma explícita un tipo
de valor de retorno. La existencia o no de parámetros es opcional. Por otro lado, la
sobrecarga permite que puedan declararse varios constructores (con el mismo
identificador que el de la clase), siempre y cuando tengan un tipo y/o número de
parámetros distinto. Por ejemplo, para la clase Fecha se declaran dos constructores, el
primero sin parámetros (por lo tanto se redefine el constructor por defecto) y el segundo
con tres parámetros:
/**
* Declaracion de la clase Fecha
*/
public class Fecha {
// Atributos o variables miembro
private int dia;

03- Programación Orientada a Objetos Página 45


Lenguaje de Programación II Prof. Melvyn Quiñones
private int mes;
private int anho;
/**
* Constructor 1
* Asigna los valores 1, 1 y 2000 a los atributos
* dia, mes y anho respectivamente
*/
public Fecha() {
this.dia = 1;
this.mes = 1;
this.anho = 2000;
}
/**
* Constructor 2
* @param ndia el dia del mes a almacenar
* @param nmes el mes del anho a almacenar
* @param nanho el anho a almacenar
*/
public Fecha(int dia, int mes, int anho) {
this.dia = dia;
this.mes = mes;
this.anho = anho;
}

public String toString() {


return this.dia + "/" + this.mes + "/" + this.anho;
}
}
La sobrecarga permite que puedan declararse varios constructores (con el mismo
identificador que el de la clase), siempre y cuando tengan un tipo y/o número de
parámetros distinto. Para probar el código anterior, se construye el siguiente programa:
/**
* Ejemplo de uso de la clase Fecha
*/
public class PruebaFecha {
public static void main (String [] args) {
Fecha origen = new Fecha();
Fecha actual = new Fecha(16,2,2009);

System.out.println("Primera fecha: " + origen.toString());


System.out.println("Segunda fecha: " + actual.toString());
}
}
El código anterior puede compilarse y ejecutarse, mostrando la siguiente salida por
pantalla:
$>javac PruebaFecha.java
Primera fecha: 1/1/2000
Segunda fecha: 16/2/2009

Importante: una vez construido un constructor ya no se puede emplear el constructor por


defecto sin parámetros. Si se desea trabajar con él, es necesario declararlo explícitamente.

03- Programación Orientada a Objetos Página 46


Lenguaje de Programación II Prof. Melvyn Quiñones

9. Herencia
La herencia es una propiedad que permite la declaración de nuevas clases a partir de otras
ya existentes. Esto proporciona una de las ventajas principales de la Programación
Orientada a Objetos: la reutilización de código previamente desarrollado ya que permite a
una clase más específica incorporar la estructura y comportamiento de una clase más
general.

Cuando una clase B se construye a partir de otra A mediante la herencia, la clase B hereda
todos los atributos, métodos y clases internas de la clase A. Además la clase B puede
redefinir los componentes heredados y añadir atributos, métodos y clases internas
específicas.

Para indicar que la clase B (clase descendiente, derivada, hija o subclase) hereda de la
clase A (clase ascendiente, heredada, padre, base o superclase) se emplea la palabra
reservada extends en la cabecera de la declaración de la clase descendiente. La sintaxis es
la siguiente:
public class ClaseB extends ClaseA {?
// Declaracion de atributos y metodos especificos de ClaseB
// y/o redeclaracion de componentes heredados
}

Por ejemplo, a partir de la clase Precio:


/**?
* Ejemplo de declaracion de la clase Precio
*/
public class Precio {?
// Variable de instancia
public double euros;?

// Metodos publicos
public double da() {
return this.euros;
}

public void pone(double x) {


this.euros = x;
}
}
se construye la clase Producto como descendiente de la clase Precio de la siguiente forma:
/**?
* Ejemplo de declaracion de la clase Producto
* clase producto desciende de Precio
*/
public class Producto extends Precio {
// Variable de instancia?
public int codigo;

03- Programación Orientada a Objetos Página 47


Lenguaje de Programación II Prof. Melvyn Quiñones
// Metodos publicos
public int daCodigo() {
return this.codigo;
}
?public void asignaCodigo(int x) {
this.codigo=x;
}

public void asignaProducto(int cod, double p) {


this.asignaCodigo(cod);?
this.pone(p);
}
?public String toString() {
return "Codigo: " + codigo + " ; precio: " + euros + " euros";
}
}

La clase PruebaClaseProducto trabaja con dos instancias de la clase Producto:


/**
* Demostracion de la clase Producto
*/
public class PruebaClaseProducto {?
public static void main (String [] args){
Producto p = new Producto();
p.asignaProducto(200201, 15.8);
System.out.println(p.toString());

Producto q = new Producto();


q.asignaCodigo(200202);
q.pone(34.3);
System.out.println(q.toString());
}
}

Durante la ejecución del código anterior, se generan las instancias, referenciadas por p y
q, cada una de las cuales está compuesta por dos atributos: euros, variable de instancia
heredada de la clase Precio y codigo, variable de instancia específica de la clase Producto.

Por otro lado, la ejecución de PruebaClaseProducto produce la siguiente salida por


pantalla:
$>javac PruebaClaseProducto.java
$>java PruebaClaseProducto?Codigo: 200201 ; precio: 15.8 euros
Codigo: 200202 ; precio: 34.3 euros

03- Programación Orientada a Objetos Página 48


Lenguaje de Programación II Prof. Melvyn Quiñones

Jerarquía de clases

Java permite múltiples niveles de herencia pero no la herencia multiple, es decir una clase
sólo puede heredar directamente de una clase ascendiente. Por otro lado, una clase
puede ser ascendiente de tantas clases descendiente como se desee (un unico padre,
multitud de hijos). En la siguiente figura se muestra gráficamente un ejemplo de jerarquía
entre diferentes clases relacionadas mediante la herencia.

Redefinición de elementos heredados

Como se ha comentado anteriormente la clase descendiente puede añadir sus propios


atributos y métodos pero también puede sustituir u ocultar los heredados. En concreto:

Se puede declarar un nuevo atributo con el mismo identificador que uno heredado,
quedando este atributo oculto. Esta técnica no es recomendable.

Se puede declarar un nuevo método de instancia con la misma cabecera que el de la clase
ascendiente, lo que supone su sobreescritura. Por lo tanto, la sobreescritura o redefinición
consiste en que métodos adicionales declarados en la clase descendiente con el mismo
nombre, tipo de dato devuelto y número y tipo de parámetros sustituyen a los heredados.

Se puede declarar un nuevo método de clase con la misma cabecera que el de la clase
ascendiente, lo que hace que éste quede oculto. Por lo tanto, los métodos de clase o
estáticos (declarados como static) no pueden ser redefinidos.

Un método declarado con el modificador final tampoco puede ser redefinido por una
clase derivada. Se puede declarar un constructor de la subclase que llame al de la
superclase de forma implícita o de mediante la palabra reservada super.

03- Programación Orientada a Objetos Página 49


Lenguaje de Programación II Prof. Melvyn Quiñones

En general puede accederse a los métodos de la clase ascendiente que han sido
redefinidos empleando la palabra reservada super delante del identificador del método.
Este mecanismo sólo permite acceder al metodo perteneciente a la clase en el nivel
inmediatamente superior de la jerarquía de clases.

La clase object

Independientemente de utilizar la palabra reservada extends en su declaración, todas las


clases derivan de una superclase llamada Object. Ésta es la clase raíz de toda la jerarquía
de clases de Java. El hecho de que todas las clases deriven implícitamente de la clase
Object no se considera herencia múltiple.

Como consecuencia, todas las clases tienen algunos métodos heredados de la clase
Object.

Es bastante frecuente tener que sobreescribir algunos de estos métodos. Por ejemplo,
para verificar si dos instancias son iguales en el sentido de contener la misma información
en sus atributos se debería sobreescribir el método equals(). El siguiente código muestra
un ejemplo de módificación de la clase Producto para incluir una sobreescritura del
método equals():

public class Producto extends Precio {


...
public boolean equals(Object a) {
if (a instanceof Producto)
return (codigo==a.daCodigo());
else return false;
}
}

03- Programación Orientada a Objetos Página 50


Lenguaje de Programación II Prof. Melvyn Quiñones

También es bastante habitual sobreescribir el método toString().

Herencia y constructores

La subclase necesita normalmente que se ejecute el constructor de la superclase antes


que su propio constructor para inicializar las variables de instancia heredadas. La solución
consiste en utilizar la palabra reservada super seguida entre paréntesis de los parámetros
correspondiente en el cuerpo del constructor de la subclase. Es decir, incluir la siguiente
sentencia como primera línea de código:
super(argumentos opcionales);

De esta forma la implementación de un constructor de la clase descendiente sólo necesita


inicializar directamente las variables de instancia no heredadas. Si no aparece como
primera sentencia, el compilador inserta una llamada implícita super(); que inicializa las
variables de instancia a cero, false, carácter nulo o null dependiendo de su tipo. Esta
llamada en cadena a los constructores de las clases ascendientes llega hasta el origen de la
jerarquía de clases, es decir, hasta el constructor de la clase Object. En cualquier caso, la
creación de una nueva instancia mediante un constructor debe tener tres fases:
 Llamada al constructor de la clase ascendiente.
 Se asignan valores a los atributos.
 Se ejecuta el resto del constructor.

Casting o moldes entre objetos con relación de herencia

El casting o moldeo permite el uso de un objeto de una clase en lugar de otro de otras
clase con el que haya una relación de herencia. Por ejemplo:
Object a = new Producto();

Entonces a es momentáneamente tanto una instancia de la clase Object como Producto


(hasta que más adelante se le asigne un objeto que no sea un Producto). A esto se le llama
moldeo implícito.

Por otro lado, si se escribe:


Producto b = a;

se obtendrá un error de compilación porque el objeto referenciado por a no es


considerado por el compilador como un Producto. Sin embargo se le puede indicar al
compilador que a la referencia a se le va a asignar obligatoriamente un Producto.
Producto b = (Producto)a;

Este moldeo explícito introduce la verificación durante la ejecución de que a la referencia


a se le ha asignado un Producto así que el compilador no genera un error. En el caso que

03- Programación Orientada a Objetos Página 51


Lenguaje de Programación II Prof. Melvyn Quiñones

durante la ejecución la referencia a no fuera a un Producto, se generaría una excepción.


Para asegurar esta situación y evitar el error de ejecución se podría emplear el operador
instanceof:
if (a instanceof Producto) {
Producto b = (Producto)a;
}

Clases y métodos abstractos (abstract)

Una clase abstracta es una clase de la que no se pueden crear instancias. Su utilidad
consiste en permitir que otras clases deriven de ella. De esta forma, proporciona un
modelo de referencia a seguir a la vez que una serie de métodos de utilidad general. Las
clases abstractas se declaran empleando la palabra reservada abstract como se muestra a
continuación:
public abstract class IdClase . . .

Una clase abstracta puede componerse de varios atributos y métodos pero debe tener, al
menos, un método abstracto (declarado también con la palabra reservada abstract en la
cabecera). Los métodos abstractos no se implementan en el código de la clase abstracta
pero las clases descendientes de ésta han de implementarlos o volver a declararlos como
abstractos (en cuyo caso la subclase también debe declararse como abstracta). En
cualquier caso, ha de indicarse el tipo de dato que devuelve y el número y tipo de
parámetros. La sintaxis de declaración de un método abstracto es:
abstract modificador tipo_retorno idClase(lista_parametros);

Si una clase tiene métodos abstractos, entonces también la clase debe declararse como
abstracta. Como los métodos de clase (static) no pueden ser redefinidos, un método
abstracto no puede ser estático. Tampoco tiene sentido que declarar constructores
abstractos ya que un constructor se emplea siempre al crear una instancia (y con las clases
abstractas no se crean instancias).

Ejemplo de código con la declaración de clase abstracta:


/**
* Declaracion de la clase abstracta FiguraGeometrica
*/
public abstract class FiguraGeometrica {
// Declaracion de atributos
private String nombre;

// Declaracion de metodos
abstract public double area();
public figuraGeometrica (String nombreFigura ) {
this.nombre = nombreFigura;
}

03- Programación Orientada a Objetos Página 52


Lenguaje de Programación II Prof. Melvyn Quiñones
final public boolean mayorQue (FiguraGeometrica otra) {
return this.area()>otra.area();
}

final public String toString()


return this.nombre + " con area " + this.area();
}
}

Como ejemplo de utilización de? Rectangulo se construye a partir de la clase abstracta


FiguraGeometrica:
/**
* Ejemplo de uso de la declaracion de una clase abstracta
* Declaracion de la clase Rectangulo
*/
public class Rectangulo extends FiguraGeometrica {
private double base;
private double altura;

public Rectangulo (double largo, double ancho) {


super("Rectangulo");
this.base = largo;
this.altura = ancho;
}

public double area () {


return this.base * this.altura;
}
}
Ejemplo de uso de la clase Rectangulo:

/**
* Ejemplo de uso de la clase Rectangulo
*/
public class pruebaRectangulo {
public static void main (String [] args ) {
Rectangulo r1;
r1 = new Rectangulo(12.5, 23.7);
System.out.println("Area de r1 = " + r1.area());

Rectangulo r2 = new Rectangulo(8.6, 33.1);


System.out.println("Area de r2 = " + r2.toString());

if (r1.mayorQue(r2))
System.out.println("El rectangulo de mayor area es r1");
else
System.out.println("El rectangulo de mayor area es r2");
}
}
Salida por pantalla de la ejecución del código anterior:
$>java PruebaRectangulo
Area de r1 = 296.25?
Area de r2 = Rectangulo con area 284.66

03- Programación Orientada a Objetos Página 53


Lenguaje de Programación II Prof. Melvyn Quiñones
El rectangulo de mayor area es r1

Clases y métodos finales (final)

Una clase declarada con la palabra reservada final no puede tener clases descendientes.
Por ejemplo, la clase predefinida de Java Math está declarada como final.

A modo de ejemplo, se desarrolla una clase final MathBis (de operatividad similar a la
clase Math estándar de Java) que incluye la declaración de dos métodos que calculan y
devuelven respectivamente las siguientes funciones trigonométricas:

El código fuente de la clase es:


/**
* Ejemplo de declaracion de una clase final
* Declaracion de la clase MathBis
*/
public final class MathBis {
public static double asinh(double x) {
return Math.log(x+Math.sqrt(x*x+1));
}
public static double acosh(double x) {
return Math.log(x+Math.sqrt(x*x-1));
}
}

Ejemplo de uso de la clase MathBis:


/**
* Ejemplo de uso de una clase final
* Declaracion de la clase pruebaMathBis
*/

public class PruebaMathBis {


public static void main (String [] args) {
for (int i=-5; i<10; i++) {
double x = i/5.0;
System.out.print("Para x = " + x);
System.out.print(": asinh(x) = " +MathBis.asinh(x));
System.out.println(", acosh(x) = " +MathBis.acosh(x));
}
}
}
Por otro lado, un método declarado como final no puede ser redefinido por una clase
descendiente. Los métodos que son llamados desde los constructores deberían declararse
como final, ya que si un constructor llama a un método que no lo sea, la subclase podría
haberla redefinido con resultados indeseables.

03- Programación Orientada a Objetos Página 54


Lenguaje de Programación II Prof. Melvyn Quiñones

10. Encapsulamiento en Java


En encapsulamiento es un principio del lenguaje Java cuya filosofía es hacer que los
atributos de las clases se puedan editar sólo a través de métodos. De manera general, se
hace teniendo las propiedades como privadas y métodos que la controlan públicos.
Comúnmente, se crean un grupo de métodos llamados getters (se encargan de obtener el
valor de la propiedad) y setters (se encargan de setearla).

Mantener las clases con el principio de encapsulamiento nos permite controlar el cambio
de valor que pueda producirse en ellas añadiendo validaciones. De cualquier manera, es
una convención dentro de la programación orientada a objetos aunque no se esté
realizando una operación adicional al cambio de valor. Veamos un ejemplo:
public class Gato {
public String nombre;
public int patas;
}
//Mi método main...
Gato g = new Gato();
g.nombre = "Nemo";
g.patas = 4;
System.out.println("Mi gato se llama: " + g.nombre);
System.out.println("El número de patas de mi gato es: " + g.patas);

En este caso, no se ha aplicado el principio de encapsulamiento, por lo que cualquier otro


desarrollador con visibilidad de nuestra clase, puede cambiar las propiedades del mismo
tan sólo con acceder a ellas, de manera muy simple.

Veamos la misma clase, con el principio de encapsulamiento:


public class Gato {
private String nombre;
private int patas;
public getNombre(){ return nombre;}
public getPatas(){ return patas;}
public setNombre(String nuevoNombre){ nombre = nuevoNombre;}
public setPatas(int numeroPatas){ patas = numeroPatas;}
}

//Mi método main...


Gato g = new Gato();
g.setNombre("Nemo");
g.setPatas(3);
System.out.println("Mi gato se llama: " + g.getNombre());
System.out.println("El número de patas de mi gato es: " +
g.getPatas());

03- Programación Orientada a Objetos Página 55


Lenguaje de Programación II Prof. Melvyn Quiñones

¿Por qué debemos aplicar el principio de encapsulamiento?

Por mantenibilidad, estabilidad y seguridad principalmente. Un segundo equipo va a usar


nuestra aplicación y por tanto nuestras clases. Nosotros conocemos perfectamente la
funcionalidad, y entre todas las cosas que sabemos y asumimos, una de ellas es que los
gatos no tienen más de 4 patas (o menos de 0). Pero sin embargo, según la estructura del
lenguaje Java, no hay nada que no impida a un desarrollador hacer esto (No con nuestra
clase actual):
g.setPatas(10);
g.setPatas(-50);

Por lo tanto, se nos ocurre, actualizar el método «setPatas» de nuestra clase Gato para
que quede así:
public void setPatas(int numeroPatas){
if(numeroPatas>=0 && numeroPatas<5){
patas = numeroPatas;
} else {
throw new IllegalArgumentException("Número de patas no
válido");
}
}
Con esta actualización del método, el segundo (tercer, cuarto, quinto..) equipo que use
nuestra clase gato, no va a variar su código (estabilidad) , seguirá llamando al método
setPatas (mantenibilidad), y nosotros controlaremos que el número sea entre 0 y 4
(seguridad). Si volvemos a la primera versión de la clase, no nos permitiría añadir este tipo
de controles a posteriori sin hacer cambiar todos los usos de nuestra clase.

Aunque parezca un ejemplo tonto (y un poco cruel para los gatos) no es raro en Java
encontrarte que tienes que trabajar con librerías que no conoces, que respetan el
principio de encapsulamiento y que gracias a él puedes hacer un correcto funcionamiento
de la misma, ya que controlará que no te salgas del tiesto, con valores inválidos, errores o
incluso validando los datos con los que se crea.

03- Programación Orientada a Objetos Página 56


Lenguaje de Programación II Prof. Melvyn Quiñones

11. Polimorfismo en Java


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");
}
}
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();
}

03- Programación Orientada a Objetos Página 57


Lenguaje de Programación II Prof. Melvyn Quiñones

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();
//salida "Woof"

b.makeSound();
//salida "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:

 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 aplican 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.

03- Programación Orientada a Objetos Página 58


Lenguaje de Programación II Prof. Melvyn Quiñones
class Overload
{
void demo (int a)
{
System.out.println ("a: " + a);
}
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:
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.

03- Programación Orientada a Objetos Página 59


Lenguaje de Programación II Prof. Melvyn Quiñones

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

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

1) ¿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

03- Programación Orientada a Objetos Página 60


Lenguaje de Programación II Prof. Melvyn Quiñones

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.

2) ¿Cuáles son las diferencias entre los términos Overloading y Overriding?

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.

3) ¿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.

4) ¿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
}
}

03- Programación Orientada a Objetos Página 61


Lenguaje de Programación II Prof. Melvyn Quiñones

12. Interfaces
Una interfaz es una especie de plantilla para la construcción de clases. Normalmente una
interfaz se compone de un conjunto de declaraciones de cabeceras de métodos (sin
implementar, de forma similar a un método abstracto) que especifican un protocolo de
comportamiento para una o varias clases. Además, una clase puede implementar una o
varias interfaces: en ese caso, la clase debe proporcionar la declaración y definición de
todos los métodos de cada una de las interfaces o bien declararse como clase abstract.
Por otro lado, una interfaz puede emplearse también para declarar constantes que luego
puedan ser utilizadas por otras clases.

 Una interfaz puede parecer similar a una clase abstracta, pero existen una serie de
diferencias entre una interfaz y una clase abstracta:
 Todos los métodos de una interfaz se declaran implícitamente como abstractos y
públicos.
 Una clase abstracta no puede implementar los métodos declarados como abstractos,
una interfaz no puede implementar ningún método (ya que todos son abstractos).
 Una interfaz no declara variables de instancia.
 Una clase puede implementar varias interfaces, pero sólo puede tener una clase
ascendiente directa.
 Una clase abstracta pertenece a una jerarquía de clases mientras que una interfaz no
pertenece a una jerarquía de clases. En consecuencia, clases sin relación de herencia
pueden implementar la misma interfaz.

Declaración de una interfaz

La declaración de una interfaz es similar a una clase, aunque emplea la palabra reservada
interface en lugar de class y no incluye ni la declaración de variables de instancia ni la
implementación del cuerpo de los métodos (sólo las cabeceras). La sintaxis de declaración
de una interfaz es la siguiente:
public interface IdentificadorInterfaz {
// Cuerpo de la interfaz ...
}
La interfaz declarada como public debe ser definida en un archivo con el mismo nombre
de la interfaz y con extensión .java. Las cabeceras de los métodos declarados en el cuerpo
de la interfaz se separan entre sí por caracteres de punto y coma y todos son declarados
implícitamente como public y abstract (se pueden omitir). Por su parte, todas las
constantes incluidas en una interfaz se declaran implícitamente como public, static y final
(también se pueden omitir) y es necesario inicializarlas en la misma sentencia de
declaración. La interfaz Modificacion declara la cabecera de un único método:

03- Programación Orientada a Objetos Página 62


Lenguaje de Programación II Prof. Melvyn Quiñones
/**
* Declaracion de la interfaz Modificacion
*/
public interface Modificacion {
void incremento(int a);
}

que se almacena en el archivo fuente Modificacion.java y que, al compilarse:


$>javac Modificacion.java

genera un archivo Modificacion.class. Al no corresponder a una clase que implementa un


método main, este archivo no puede ejecutarse con el intérprete de Java.

Segundo ejemplo: la interfaz constantes declara dos constantes reales con el siguiente
código fuente:
/**
* Declaracion de la interfaz Constantes
*/
public interface Constantes {
double VALOR_MAXIMO = 10000000.0;
double VALOR_MINIMO = -0.01;
}

que se almacena en el archivo fuente Constantes.java y que, al compilarse, genera un


archivo Constantes.class

Tercer ejemplo: la interfaz Numerico declara una constante real y dos cabeceras de
métodos con el siguiente código fuente:
/**
* Declaracion de la interfaz Numerico
*/
public interface Numerico {
double EPSILON = 0.000001;
void establecePrecision(float p);
void estableceMaximo(float m);
}

que se almacena en el archivo fuente Numerico.java y que, al compilarse, genera un


archivo Numerico.class.

Implementación de una interfaz en una clase

Para declarar una clase que implemente una interfaz es necesario utilizar la palabra
reservada implements en la cabecera de declaración de la clase. Las cabeceras de los
métodos (identificador y número y tipo de parámetros) deben aparecer en la clase tal y
como aparecen en la interfaz implementada. Por ejemplo, la clase Acumulador
implementa la interfaz Modificacion y por lo tanto debe declarar un método incremento:
03- Programación Orientada a Objetos Página 63
Lenguaje de Programación II Prof. Melvyn Quiñones
/**
* Declaracion de la clase Acumulador
*/
public class Acumulador implements Modificacion {
private int valor;

public Acumulador (int i) {


this.valor = i;
}

public int daValor () {


return this.valor;
}

public void incremento (int a) {


this.valor += a;
}
}

Esta cabecera con la palabra implements... implica la obligación de la clase Acumulador de


definir el método incremento declarado en la interfaz Modificacion. El siguiente código
muestra un ejemplo de uso de la clase Acumulador.
/**
* Demostracion de la clase Acumulador
*/
public class PruebaAcumulador {
public static void main (String [] args) {
Acumulador p = new Acumulador(25);
p.incremento(12);
System.out.println(p.daValor());
}
}
La compilación y posterior ejecución del código anterior origina la siguiente salida por
pantalla:
$>javac PruebaAcumulador.java
$>java PruebaAcumulador
37

La clase Acumulador tendría también la posibilidad de utilizar directamente las constantes


declaradas en la interfaz si las hubiera. Para poder emplear una constante declarada en
una interfaz, las clases que no implementen esa interfaz deben anteponer el identificador
de la interfaz al de la constante.

Jerarquía entre interfaces;63

La jerarquía entre interfaces permite la herencia simple y múltiple. Es decir, tanto la


declaración de una clase, como la de una interfaz pueden incluir la implementación de
otras interfaces. Los identificadores de las interfaces se separan por comas. Por ejemplo,
la interfaz Una implementa otras dos interfaces: Dos y Tres.

03- Programación Orientada a Objetos Página 64


Lenguaje de Programación II Prof. Melvyn Quiñones
public interface Una implements Dos, Tres {
// Cuerpo de la interfaz ...
}
Las clases que implementan la interfaz Una también lo hacen con Dos y Tres.

Otro ejemplo: pueden construirse dos interfaces, Constantes y Variaciones, y una clase,
Factura, que las implementa:
// Declaracion de la interfaz Constantes
public interface Constantes {
double valorMaximo = 10000000.0;
double valorMinimo = -0.01;
}
// Declaracion de la interfaz Variaciones
public interface Variaciones {
void asignaValor(double x);
void rebaja(double t);
}
// Declaracion de la clase Factura
public class Factura implements Constantes, Variaciones {
private double totalSinIVA;
public final static double IVA = 0.16;

public double sinIVA() {


return this.totalSinIVA;
}
public double conIVA() {
return this.totalSinIVA * (1+IVA);
}
public void asignaValor(double x) {
if (this.valorMinimo<x)
this.totalSinIVA=x;
else
this.totalSinIVA=0;
}
public void rebaja(double t) {
this.totalSinIVA *= (1-t/100);
}
public static void main (String [] args) {
factura a = new Factura();
a.asignaValor(250.0);

System.out.println("El precio sin IVA es: " + a.sinIVA());


System.out.println("El precio con IVA es: " + a.conIVA());
System.out.println("Rebajado durante el mes de mayo un 20%");
a.rebaja(20);
System.out.println("Rebajado sin IVA es: " + a.sinIVA());
System.out.println("Rebajado con IVA es: " + a.conIVA());
}
}
Si una interfaz implementa otra, incluye todas sus constantes y declaraciones de métodos,
aunque puede redefinir tanto constantes como métodos.

03- Programación Orientada a Objetos Página 65


Lenguaje de Programación II Prof. Melvyn Quiñones

Importante: Es peligroso modificar una interfaz ya que las clases dependientes dejan de
funcionar hasta que éstas implementen los nuevos métodos.

Una clase puede simultáneamente descender de otra clase e implementar una o varias
interfaces. En este caso la seccion implements se coloca a continuación de extends en la
cabecera de declaración de la clase. Por ejemplo:
public class ClaseDescendiente extends ClaseAscendiente implements
Interfaz {
...
}

Utilización de una interfaz como un tipo de dato

Al declarar una interfaz, se declara un nuevo tipo de referencia. Pueden emplearse


identificadores de interfaz en cualquier lugar donde se pueda utilizar el identificador de un
tipo de dato (o de una clase). El objetivo es garantizar la sustituibilidad por cualquier
instancia de una clase que la implemente. Por ejemplo, puede emplearse como tipo de un
parámetro de un método:
public class Calculos {
public void asignacion(Variaciones x);
{
...
}
}

Sólo una instancia de una clase que implemente la interfaz puede asignarse al parámetro
cuyo tipo corresponde al identificador de la interfaz. Esta facultad se puede aprovechar
dentro la propia interfaz. Por ejemplo:
public interface Comparable {?
// La instancia que llama a esMayor (this) y el parametro otra?
// deben ser de la misma clase o de clases que implementen esta
interfaz
// La funcion devuelve 1, 0, -1 si this es mayor, igual o menor
que otra
public int esMayor(Comparable otra);
}

En algún caso puede ser útil declarar una interfaz vacía como, por ejemplo:
public interface Marcador { }

Esta declaración es totalmente válida ya que no es obligatorio incluir dentro de una


interfaz la declaración de una constante o la cabecera de un método. La utilidad de estas
interfaces reside en la posibilidad de ser empleadas como tipos de dato para especificar
clases sin necesidad de obligar a éstas a implementar algún método en concreto. Una
interfaz no es una clase pero se considera un tipo en Java y puede ser utilizado como tal.

03- Programación Orientada a Objetos Página 66


Lenguaje de Programación II Prof. Melvyn Quiñones

13. Paquetes en Java


Un paquete es una colección de clases relacionadas. Ayuda a organizar sus clases en una
estructura de carpetas y facilita su localización y uso. Más importante aún, ayuda a
mejorar la reutilización.

Cada paquete en Java tiene su nombre único y organiza sus clases e interfaces en un
espacio de nombres o grupo de nombres separados.

Aunque las interfaces y las clases con el mismo nombre no pueden aparecer en el mismo
paquete, pueden aparecer en diferentes paquetes. Esto es posible asignando un espacio
de nombre separado a cada paquete.

Sintaxis:
paquete nameOfPackage;

Definimos una clase y un objeto y luego lo compilamos en nuestro paquete p1. Después
de la compilación, ejecutamos el código como un paquete java:

Paso 1. Considere el siguiente código:

Donde:

1) Para poner una clase en un paquete, en la primera línea de código define el paquete
p1
2) Crea una clase c1
3) Definiendo un método m1 que imprime una línea.
4) Definiendo el método principal
5) Creando un objeto de clase c1
6) Método de llamada m1

03- Programación Orientada a Objetos Página 67


Lenguaje de Programación II Prof. Melvyn Quiñones

Paso 2. En el siguiente paso, guarde este archivo como demo.java:

Paso 3. En este paso, compilamos el archivo.

La compilación está completa. Se crea un archivo de clase c1. Sin embargo, no se crea
ningún paquete. El siguiente paso tiene la solución.

Paso 4. Ahora tenemos que crear un paquete, use el comando:


javac -d. demo.java

Este comando obliga al compilador a crear un paquete.

El “.” operador representa el directorio de trabajo actual.

03- Programación Orientada a Objetos Página 68


Lenguaje de Programación II Prof. Melvyn Quiñones

Paso 5. Cuando ejecuta el código, crea un paquete p1. Cuando abras el paquete java p1
dentro, verás el archivo c1.class.

Paso 6. Compila el mismo archivo usando el siguiente código:


javac -d .. demo.java

Aquí “..” indica el directorio principal. En nuestro caso, el archivo se guardará en el


directorio principal que es C Drive

Archivo guardado en el directorio principal cuando se ejecuta el código anterior.

Paso 7. Ahora digamos que desea crear un paquete secundario p2 dentro de nuestro
paquete java existente p1. Entonces modificaremos nuestro código como:
paquete p1.p2

03- Programación Orientada a Objetos Página 69


Lenguaje de Programación II Prof. Melvyn Quiñones

Paso 8. Compila el archivo:

Como se ve en la captura de pantalla siguiente, crea un subpaquete p2 que tiene la clase


c1 dentro del paquete.

Paso 9. Para ejecutar el código, mencione el nombre completo de la clase, es decir, el


nombre del paquete seguido del nombre del paquete secundario seguido del nombre de
la clase:
java p1.p2.c1

Así es como se ejecuta el paquete y da el resultado como “m1 de c1” desde el archivo de
código.

03- Programación Orientada a Objetos Página 70


Lenguaje de Programación II Prof. Melvyn Quiñones

Importar paquetes

Para crear un objeto de una clase (incluido en un paquete), en su código, debe usar su
nombre completo.

Ejemplo:
java.awt.event.actionListner object= new java.awt.event.actionListner ();

Sin embargo, podría ser tedioso escribir el nombre de ruta del paquete separado por
puntos para cada clase que desee utilizar. En cambio, se recomienda que use la
declaración de importación.

Sintaxis:
import packageName;

Una vez importado, puede usar la clase sin mencionar su nombre completamente
calificado.
import java.awt.event. *;
// * significa que todas las clases en este paquete son importadas
import javax.swing.JFrame // aquí solo se importa la clase JFrame
//Uso
JFrame f = nuevo JFrame; // sin nombre completamente calificado.

Ejemplo de importación el paquete

Paso 1. Copie el código en un editor.


paquete p3;
// importa clases solo en el paquete p1 y NO en el subpaquete p2
importar p1.*;
clase c3 {
vacío público m3() {
System.out.println("Método m3 de la Clase c3");
}
public static void main(String args[]) {
c1 obj1 = nuevo c1();
obj1.m1();
}
}

Paso 2. Guarde el archivo como Demo2.java. Compila el archivo usando el comando javac
-d. Demo2.java

Paso 3. Ejecuta el código usando el comando java p3.c3

03- Programación Orientada a Objetos Página 71


Lenguaje de Programación II Prof. Melvyn Quiñones

Puntos a tener en cuenta

Para evitar nombrar conflictos, los paquetes reciben los nombres del nombre de dominio
de la compañía en Ex inverso: com.guru99. com.microsoft, com.infosys etc.

Cuando no se especifica un nombre de paquete, una clase está en el paquete


predeterminado (el directorio de trabajo actual) y el paquete en sí no recibe ningún
nombre. Por lo tanto, fue capaz de ejecutar asignaciones antes.

Al crear un paquete, se debe tener cuidado de que la declaración para crear el paquete se
debe escribir antes que cualquier otra declaración de importación:

// No permitido
import el paquete p1. *;
paquete p3;

// sintaxis correcta
paquete p3;
import el paquete p1. *;

El paquete java.lang se importa de forma predeterminada para cualquier clase que cree
en Java.

La API de Java es muy extensa, contiene clases que pueden realizar casi todas sus tareas
de programación desde la manipulación de la estructura de datos hasta la creación de
redes. La mayoría de las veces, usará archivos API en su código.

Protección de acceso

Dada la interacción entre clases y paquetes, Java establece cuatro categorías de visibilidad
para los miembros de clase:
 Subclases del mismo paquete
 No subclases del mismo paquete
 Subclases de diferentes paquetes
 Clases que no están en el mismo paquete ni a las subclases

Los especificadores de acceso: private, public, protected proporcionan una gran variedad
de formas para producir los diferentes niveles de acceso que necesitan. La siguiente tabla
resume las interacciones:

03- Programación Orientada a Objetos Página 72


Lenguaje de Programación II Prof. Melvyn Quiñones

Examinemos cada opción de acceso individualmente.

Si un miembro de una clase no tiene un modificador de acceso explícito, entonces es


visible dentro de su paquete pero no fuera de su paquete. Por lo tanto, utilizará la
especificación de acceso predeterminada (default) para los elementos que desea
mantener en privado para un paquete pero público dentro de ese paquete.

Los miembros explícitamente declarados públicos (public) son los más visibles, y se puede
acceder desde diferentes clases y diferentes paquetes.

Un miembro privado (private) es accesible solo para los otros miembros de su clase. Un
miembro privado no se ve afectado por su membresía en un paquete.

Se puede acceder a un miembro especificado como protegido (protected) dentro de su


paquete y a subclases en otros paquetes.

Una clase de nivel superior tiene solo dos niveles de acceso posibles: predeterminado y
público. Cuando una clase se declara como pública, se puede acceder fuera de su paquete.
Si una clase tiene acceso predeterminado, solo se puede acceder por otro código dentro
de su mismo paquete. Además, una clase que se declara pública debe residir en un archivo
con el mismo nombre.

Los paquetes y el CLASSPATH

¿Cómo sabe el intérprete de Java donde debe buscar los paquetes que se van creando? En
primer lugar la interpreta utiliza por defecto el directorio de trabajo como punto de
partida, por lo tanto lo encontrará si el paquete está en este directorio o en un
subdirectorio. En segundo lugar, se puede especificar una ruta de directorio, ajustando la
variable de entorno CLASSPATH.

03- Programación Orientada a Objetos Página 73


Lenguaje de Programación II Prof. Melvyn Quiñones

EJERCICIOS DE EVALUACIÓN
Contesta.
1. ¿Qué es la Programación Orientada a Objetos (POO)?
2. ¿Cuál fue el primer lenguaje de programación que utilizó POO y quiénes lo crearon?
3. ¿En qué difiere la POO de la programación estructurada?
4. Defina los siguientes conceptos:
 Evento
 Atributos
 Mensaje
 Propiedad o atributo
 Estado interno
 Miembros de un objeto
 Identificación de un objeto
 variable
 firma
5. Defina las características de la POO.
6. ¿Cuál es la corriente de POO que utiliza el lenguaje Java y por qué?
7. ¿Qué es un objeto?
8. ¿Qué es un campo o atributo?
9. ¿Qué es una rutina o método?
10. ¿Qué es una clase?
11. ¿Cómo deben nombrarse los identificadores de las clases?
12. ¿Qué es una instancia?
13. Elabore una porción de código que describa la instanciación de una clase.
14. ¿Qué es una referencia o puntero?
15. ¿Para qué sirve el operador instanceof?
16. Defina los modificadores de visibiliad o acceso.
17. Mencione 10 lenguajes que utilizan POO.
18. ¿Qué son variables de instancia?
19. ¿Qué son variables de clase?
20. ¿Para qué sirve la palabra reservada "final"?
21. Elabore una porción de código que describa el uso de variables de tipo final.
22. ¿Qué son los wrappers?
23. Mencione las clases contenedoras o wrappers de los tipos de datos primitivos en java.
24. Defina los métodos que componen la clase Character.

03- Programación Orientada a Objetos Página 74


Lenguaje de Programación II Prof. Melvyn Quiñones

25. Defina los métodos que componen la clase String.


26. ¿Para qué sirve la clase Array?
27. ¿En consisten las matrices en java?
28. Elabore una porción de código que describa la declaración de una método.
29. ¿Para qué sirve la palabara reservada "void"?
30. ¿Para qué sirve la palabara reservada "return"?
31. ¿En qué consiste la recursión?
32. ¿En qué consiste la Sobrecarga de métodos?
33. Defina los tipos de métodos.
34. ¿Qué son los parámetros o argumentos?
35. ¿Cómo se declaran los parámetros?
36. ¿Para qué se utiliza la palabra reservada "this"?
37. ¿En qué consiste el paso por valor y paso por referencia?
38. ¿Para qué se utilizan las variables locales?
39. ¿Qué es un constructor y para qué se utiliza?
40. Escriba la declaración de un constructor.
41. ¿Qué es la herencia y para qué se utiliza?
42. Elabore una porción de código que describa la utilización de la herencia.
43. ¿En qué consiste la jerarquía de clases?
44. ¿Para qué se utiliza la clase object?
45. Defina los métodos que componen la clase Object.
46. ¿Para qué se utiliza la palabra reservada "super"?
47. ¿En qué consiste el Casting o moldes entre objetos?
48. ¿Qué es una clase abstracta?
49. ¿En qué consiste el encapsulamiento?
50. ¿Por qué debemos aplicar el principio de encapsulamiento?
51. Elabore una porción de código que describa la utilización del encapsulamiento.
52. ¿En qué consiste el polimorfismo?
53. Defina los 3 tipos de polimorfismo
54. Elabore una porción de código que describa la utilización del polimorfismo.
55. Diga con sus propias palabras la diferencia entre polimorfismo y sobrecarga.
56. ¿Cuáles son las diferencias entre los términos Overloading y Overriding?
57. ¿Qué es una interfaz?
58. Elabore una porción de código que describa la implementación de una interfaz en una
clase.
59. Elabore una porción de código que describa la implementación de una interfaz como
un tipo de dato.
60. ¿Qué es un paquete?

03- Programación Orientada a Objetos Página 75


Lenguaje de Programación II Prof. Melvyn Quiñones

REFERENCIAS
https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos

https://www.arkaitzgarro.com/java

https://javadesdecero.es/poo/modificadores-de-acceso/

https://juanjavierrg.com/java-basico-encapsulamiento/

https://guru99.es/java-packages/#top

https://javadesdecero.es/intermedio/paquetes-en-java/

https://www.pcresumen.com/menu-software/35-lenguajes-de-programacion/java/72-los-
paquetes-en-java

https://www.tutorialesprogramacionya.com/javaya/

03- Programación Orientada a Objetos Página 76

También podría gustarte