Programación orientada al objeto II - 6502.cl

Anuncio
INACAP
Universidad Tecnológica de Chile
Sede Santiago Centro
Taller de Programación I
Curso Java J2SE
Tema 06:
Orientación al Objeto en Java
(parte 2)
Ing. Manuel López Ramos
(versión 1)
Parte I
Trabajo con objetos de Java
1) Clases y objetos
●
Las clases de Java permiten ENCAPSULAR datos dentro de un mismo nombre de variable.
●
Las clases también permiten DEFINIR métodos (o acciones) para todos los objetos de dicha clase.
●
Luego de definir una clase, se puede crear una INSTANCIA de dicha clase con la palabra clave new.
1) Clases y objetos
●
●
Conceptos nuevos: ENCAPSULAMIENTO
DEFINICIÓN DE CLASE
INSTANCIA DE CLASE
Ejemplo: clase Perro y creación de 2 instancias de clase (objetos)
class Perro
{
String nombre;
String raza;
float peso;
char sexo;
}
●
...
...
Perro p1 = new Perro();
Perro m1 = new Perro();
Al crear una instancia de clase, se puede imaginar como se muestra a continuación.
a) Descripción del objeto en memoria RAM
(datos de muestra)
b) Descripción en diagrama de objetos de UML
(datos de muestra)
1) Clases y objetos
●
Otro ejemplo: clase Archivo y creación de 2 instancias de clase (objetos)
class Archivo
{
String ruta;
String tipo;
String fechaCreación;
int idDueño;
Archivo(){}
}
Archivo(String r)
{
this.ruta = r;
}
...
...
Archivo f1 = new Archivo();
Archivo f2 = new Archivo("/usr");
1) Clases y objetos
●
Representación de las instancias de clase:
...
...
Archivo f1 = new Archivo();
Archivo f2 = new Archivo("/usr");
a) Creación de instancias
b) Descripción del objeto en memoria RAM
c) Descripción en diagrama de objetos de UML
2) Visibilidad o tipos de acceso a datos
La visibilidad es otro concepto importante en las aplicaciones de Java. Indica cómo acceder
a los atributos y métodos de una clase en la aplicación.
●
●
Existen 4 tipos de visibilidad:
1) de paquete: los atributos y métodos sólo pueden usarse dentro del paquete
actual. No usan símbolo en UML y tampoco tienen una palabra clave en Java.
2) pública: los atributos y métodos pueden usarse desde cualquier parte de la
aplicación. Se simboliza en UML con un signo de adición (+) y en Java con la palabra
clave public.
3) privada: los atributos y métodos sólo pueden usarse desde dentro de la clase
donde se definieron. Se simboliza en UML con un signo de resta (-) y en Java con la
palabra clave private.
4) protegida: los atributos y métodos sólo pueden usarse dentro de la clase donde
están definidos y desde clases hijas en herencia. Se simboliza en UML con un signo
de gato (#) y en Java con la palabra clave protected.
2) Visibilidad
●
Tipos de visibilidad:
Visibilidad
Palabra clave
Símbolo de UML
por defecto
(de paquete)
(no tiene)
privada
(no usa palabra
clave)
private
protegida
protected
#
pública
public
+
-
2) Visibilidad
Como regla general, los atributos deberían declararse como privados (para evitar el
acceso directo desde la aplicación) y los métodos deberían declararse como públicos
(para utilizarlos en los programas con libertad) -> ENCAPSULAMIENTO de datos
●
●
Las clases deberían ser públicas (hay excepciones).
●
Se debería definir una clase por archivo (por orden, pero hay excepciones).
public class Perro
{
private String nombre;
private String raza;
private float peso;
private char sexo;
}
public class Archivo
{
private String ruta;
private String tipo;
private String fechaCreación;
private int idDueño;
public Archivo(){}
}
a) Archivo Perro.java
public Archivo(String r)
{
this.ruta = r;
}
b) Archivo Archivo.java
2) Visibilidad
Para acceder a atributos no privados, se puede utilizar directamente la notación de
punto. Por ejemplo, si se quiere obtener el nombre de un objeto Perro p:
●
...
...
Perro p = new Perro("Rex", "Boxer", 45, 8.9F);
String nombrePerro = p.nombre; // Acceso directo a
String razaPerro = p.raza;
// los atributos
...
// del objeto.
...
NOTA: Esto funciona sólo si los atributos nombre y raza de la clase Perro se declaran como public.
Para acceder a atributos privados, se hace necesario utilizar métodos selectores
(getters) y mutadores (setters).
●
Parte II
Tipos de métodos
3) Estructura de una clase
●
Las clases de Java internamente comprenden los siguientes elementos:
●
lista de atributos
●
métodos constructores
●
métodos selectores (getters)
●
métodos mutadores (setters)
●
métodos de clase generales (o métodos comunes)
●
métodos estáticos
●
método main (opcional)
3) Estructura de una clase
Cada uno de los elementos indicados permite identificar diferentes aspectos
dentro del programa y de la aplicación.
●
●
●
●
●
●
●
Lista de atributos: define los campos donde se almacenarán los datos de los
objetos.
Método constructor: crea instancias de clase e inicializa sus atributos.
Métodos selectores: recuperan los datos almacenados en los atributos de
una instancia.
Métodos mutadores: modificar los datos de los atributos de una instancia de
clase.
Métodos estáticos: aquellos que no necesitan ejecutarse sobre una instancia
de clase.
Métodos generales (o comunes): aquellos que representan las operaciones
propias y reales del concepto a modelar mediante la
clase.
4) Métodos constructores
Los métodos constructores permiten crear instancias de clase e inicializar sus
atributos, si se desea.
●
●
Un método constructor se define utilizando la sintaxis:
public <nombre_de_la_clase>(parámetros_iniciales)
{
// inicialización de atributos.
}
por lo que un método constructor no tiene tipo de retorno explícito (es decir, escrito
en el código).
Si no se crea un método constructor explícito (a mano), Java entrega uno,
denominado como el constructor por defecto de la clase. Este constructor no
tiene parámetros de entrada y, por lo general, sólo crea al objeto, pero no lo
inicializa más que con valores por omisión.
●
4) Métodos constructores
Pueden existir varios métodos constructores, pero deben diferenciarse en una de las
siguientes características:
●
a) cantidad de parámetros de entrada.
b) tipos y orden de los parámetros de entrada.
Por ejemplo:
public NumeroComplejo()
{
...
}
public NumeroComplejo(double parteReal)
{
...
}
public NumeroComplejo(float parteImaginaria)
{
...
}
public NumeroComplejo(double parteReal, double parteImaginaria)
{
...
}
4) Métodos constructores
Los métodos constructores tienen por misión inicializar los objetos antes de su
uso. Por lo tanto, sólo deberían incluir código de inicialización de atributos en base a
valores por omisión o a parámetros de entrada. Por ejemplo:
●
public class ListaUsuarios
{
private int maxUsuarios;
private int diaCreacion, mesCreacion;
private String nombre, creadorLista;
public ListaUsuarios(int numMaxUsuarios, String nombre)
{
this.maxUsuarios = numMaxUsuarios;
// valor parametrizado
this.nombre
= nombre;
this.creadorLista= "";
// valor por omisión
this.diaCreacion = 1;
this.mesCreacion = 1;
}
}
...
...
4) Métodos constructores (uso de this)
Nótese que para referenciar a un atributo (ya sea para lectura o escritura de un
valor) se usa normalmente la palabra reservada this.
●
La palabra reservada this indica que el atributo a utilizar es el del objeto a crear y
no el atributo de algún otro objeto del programa.
●
...
}
public ListaUsuarios(int numMaxUsuarios, String nombre)
{
this.maxUsuarios = numMaxUsuarios;
// valor parametrizado
this.nombre
= nombre;
this.creadorLista= "";
// valor por omisión
this.diaCreacion = 1;
this.mesCreacion = 1;
}
...
...
La palabra this puede utilizarse en cualquier método dentro de la clase (ya sea
un constructor, selector, mutador o método general). Sólo se prohíbe su uso dentro
de métodos estáticos (a estudiar más adelante).
●
5) Métodos selectores
Los métodos selectores (o métodos getters) permiten recuperar los datos
almacenados en los atributos de una instancia.
●
Su función consiste en dar acceso a los atributos privados de un objeto para leer
los datos en ellos.
●
●
Su forma de creación es estándar y se mustra a continuación:
public <tipo_atributo> get<nombre_atributo>()
{
return this.<nombre_atributo>;
}
a) Sintaxis básica de escritura
de un selector en Java.
b) Ejemplo de selectores
en la clase Perro
class Perro
{
String nombre;
String raza;
float peso;
char sexo;
...
...
public String getNombre()
{
return this.nombre;
}
}
public float getPeso()
{
return this.peso;
}
... // etc.
6) Métodos mutadores
Los métodos mutadores (o métodos setters) permiten recuperar los datos
almacenados en los atributos de una instancia.
●
Su función consiste en dar acceso a los atributos privados de un objeto para
escribir nuevos datos en ellos.
●
●
Su forma de creación también es estándar y se mustra a continuación:
public void set<nombre_atributo>(<tipo> <param>)
{
this.<nombre_atributo> = <param>;
}
a) Sintaxis básica de escritura
de un mutador en Java.
b) Ejemplo de mutadores
en la clase Perro
class Perro
{
String nombre;
String raza;
float peso;
char sexo;
...
...
public void setNombre(String v)
{
this.nombre = v;
}
}
public void setPeso(float v)
{
this.peso = v;
}
... // etc.
7) Métodos generales de clases
Los métodos generales de clases representan las operaciones propias del
concepto que se está representando. Por ejemplo:
●
●
Clase Perro: métodos ladrar(), comer(), dormir(), nacer(), etc.
●
Clase Edificio: métodos construir(), demoler(), pintar(), etc.
●
Clase Avion: métodos volar(), aterrizar(), planear(), etc.
En estos tipos de métodos, el tipo de retorno y los parámetros de entrada se
definen de acuerdo al problema; no hay una directriz obligatoria al respecto.
●
8) Atributos y métodos estáticos
Los métodos anteriormente vistos (a excepción del constructor) deben ser
aplicados sobre una instancia de clase (creada con la palabra clave new). Por
ejemplo:
●
...
...
Perro p1 = new Perro();
p1.setNombre("Lassie");
p1.setRaza("Beagle");
p1.setPeso(8.9F);
p1.setSexo('M');
float pesoActual = p1.getPeso();
p1.ladrar();
p1.comer();
p1.dormir();
...
... // etc.
8) Atributos y métodos estáticos
Sin embargo, hay oportunidades en las cuales conviene crear métodos que se
puedan aplicar sin objetos, es decir, "en el aire" o "de forma individual y directa". O
dicho de otra forma: métodos que se puedan aplicar a la clase y no a un objeto
individual.
●
Por ejemplo: supóngase que se necesita un método de la clase Perro que cuente
el número total de perros creados en la aplicación. Se desprende de esto que un
perro individual no tiene que llevar la contabilización de los demás, sino que más
bien la clase debe registrar dicho valor.
●
Para esto, se utilizará un atributo estático; es decir, que pertenezca a la clase
completa y no sólo a un objeto en particular.
●
9) Atributos estáticos
public class Perro
{
private String nombre, raza;
...
...
private static int numPerrosCreados = 0;
public Perro()
{
this.nombre = "";
this.raza
= "";
numPerrosCreados++;
}
}
// Llamada a atributo estático
9) Atributos estáticos
public class Perro
{
private String nombre, raza;
...
...
private static int numPerrosCreados = 0;
public Perro()
{
this.nombre = "";
this.raza
= "";
numPerrosCreados++;
}
// Llamada a atributo estático
}
Nótese que para llamar al atributo estático, no puede utilizarse la palabra clave
this.
●
El atributo estático numPerrosCreados no pertenece a un objeto en particular, sino
que a la clase completa.
●
10) Métodos estáticos
●
Para acceder a atributos estáticos también suele utilizarse métodos estáticos.
Por ejemplo: supóngase que se necesita también un método que lleve a cero al
atributo del ejemplo anterior. Entonces se creará el método estático
reiniciarContadorPerros (usando la palabra clave static) para realizar tal
acción.
●
public class Perro
{
private String nombre, raza;
...
...
private static int numPerrosCreados = 0;
public Perro()
{
this.nombre = "";
this.raza
= "";
numPerrosCreados++;
}
}
// Llamada a atributo estático
public static void reiniciarContadorPerros()
{
numPerrosCreados = 0;
}
10) Métodos estáticos
Finalmente, para utilizar un método estático desde el programa principal, se
indicará el nombre de la clase y el nombre del método, como se muestra a
continuación:
●
public class TestPerro
{
public static void main(String[]
{
Perro p1 = new Perro();
Perro p2 = new Perro();
Perro p3 = new Perro();
//
//
//
}
}
args)
Hasta acá se habrán
contabilizado ya
3 perros nuevos.
Perro.reiniciarContadorPerros();
// Vuelve el conteo a cero.
Parte III
Referencias a objetos
Implementación de relaciones entre clases
Cuando se necesita implementar relaciones entre clases en código, es importante
fijarse en dos aspectos:
●
1) la dirección de la relación
2) la cardinalidad de la relación
Supóngase que se necesita implementar las siguientes relaciones entre clases en
una aplicación en Java:
●
Implementación de relaciones entre clases
●
Nótese que hay 2 relaciones:
* relación AppMascota03 con Amo ("1 AppMascota03 tiene 2 Amos")
* relación Amo con Perro ("1 Amo tiene 1 Perro")
●
En Java, la implementación de relaciones se traduce en:
"crear un objeto de una de las clases dentro de la clase opuesta"
Implementación de relaciones entre clases
Pero, ¿qué clase entrega un objeto y cuál lo recibe? En general, se puede seguir
la siguiente regla (para relaciones unidireccionales):
●
"se deben crear objetos de la clase con mayor cardinalidad
dentro de la clase con menor cardinalidad"
●
De esta forma, la clase AppMascota03 recibe 2 instancias (objetos) de la clase Amo.
Implementación de relaciones entre clases
Amo a1 = new Amo(...);
Amo a2 = new Amo(...);
Pero, ¿y si la cardinalidad es 1-a-1? En general, se puede seguir otra regla
(también para relaciones unidireccionales):
●
"se deben crear objetos de la clase que tenga la 'punta de flecha' (de la relación)
dentro de la clase opuesta a la 'punta de flecha' "
●
De esta otra forma, la clase Amo recibe 1 instancia (objeto) de la clase Perro.
Implementación de relaciones entre clases
Perro p1 = new Perro(...);
Pero, ¿y si la cardinalidad es 1-a-1? En general, se puede seguir otra regla
(también para relaciones unidireccionales):
●
"se deben crear objetos de la clase que tenga la 'punta de flecha' (de la relación)
dentro de la clase opuesta a la 'punta de flecha' "
●
De esta otra forma, la clase Amo recibe 1 instancia (objeto) de la clase Perro.
Implementación de relaciones entre clases
●
Finalmente, las clases quedarían escritas de la siguiente forma:
public class Amo
{
private Perro p1;
}
public class Perro
{
...
...
}
public class AppMascota03
{
private static Amo a1;
private static Amo a2;
}
public static void main(String[] args)
{
a1 = new Amo("", 'M');
a2 = new Amo("", 'F');
...
...
}
public Amo(String nom, char sex)
{
this.p1 = new Perro();
...
}
...
Nótese que los objetos deben crearse, usando new. Si
no se hace, la cardinalidad implementada sería de cero, lo
cual no cumple con lo solicitado.
●
También nótese que los atributos generados en la clase
principal se declaran como estáticos para poder utilizarlos
desde el método main.
●
Conclusión
Finalmente, para diagramas de UML más grandes (con más clases, con más
relaciones, etc.):
●
a) identificar todas las relaciones entre clases. Cada una de ellas generará un
atributo en otra clase.
b) leer correctamente la cardinalidad de la relación. Esta indica cuántos
objetos crear dentro de la clase correspondiente.
c) Para relaciones bidireccionales se sigue otro procedimiento (se indicará
más adelante).
d) Para cardinalidades mayores a 3, se necesitará implementar un arreglo de
objetos, o bien, una lista de objetos (ArrayList o LinkedList).
Parte III
Uso de métodos
con referencias a objetos
Referencias a objetos en relación
Cuando ya se comprende cómo crear las relaciones entre clases, se hace
necesario entender ahora cómo utilizar los objetos generados por dichas relaciones.
●
Aquí es donde se puede apreciar la importancia de contar con métodos selectores
(getters) y mutadores (setters), ya que éstos son los que permiten acceder a
atributos con visibilidad privada (private) dentro de un objeto.
●
El siguiente análisis se realizará en base al diagrama de clases de UML de la
sección anterior:
●
Referencias a objetos en relación
Diagrama de clases de la sección anterior:
AppMascota-Amo-Perro
Parte IV
Trabajo avanzado con objetos
Descargar