5.
4 Java Library 1
Packages
Higo. 5.5 “ Organizar las importaciones ” El cuadro de diálogo aparece si hay varias clases
que tienen el mismo nombre
Ejercicio 5.3
• Crear a clase con a " principal " método.
• En " principal " , crear a nuevo Fecha objeto (de el p a q u e t e “ [Link] ”
). Usar la declaración de “ importación ” necesaria .
• Crear a Cadena objeto eso contiene el mismo fecha por explícitamente usando el
“ aCadena ” método de el Fecha clase.
• Crear otro cadena objeto eso contiene el mismo fecha convertido a superior caso.
• Mostrar el mensaje “ La fecha de hoy es … ” seguido de tu letra mayúscula
. cadena utilizando una única declaración “ [Link] ” .
5.2 Usando Javadoc
Como nosotros tener comenzó a usar el clases en el Java bibliotecas, tú voluntad
No duda desear encontrar afuera más acerca de estos clases, y otros, y cómo ellos
poder ser usado. Todo de Esta información es hecho disponible en el Java
documentación, cual poder ser visto
2 5 Creating
Objects
Higo. 5.6 El índice página de el Javadoc documentación para Java 14
En línea en “ [Link] ” o descargarse desde el sitio
de Oracle Java (es una descarga independiente, no incluida en el JDK) y
visualizarse como páginas HTML locales. Esta documentación se ha creado
utilizando la herramienta Javadoc, que genera documentos a partir del código
fuente de Java y comentarios de estilo Javadoc. Todo el JDK está ahora
modularizado, por lo que encontrará todos los paquetes que aparecen en módulos.
El módulo más importante con el que debe familiarizarse es [Link], porque
contiene todas las API fundamentales.
Si decide descargar la documentación en lugar de leerla en línea, la estructura
de carpetas incluye una carpeta llamada “ docs ” . Dentro de esta hay una
página “ [Link] ” que puede abrir en un navegador (Fig. 5.6 ). Esta contiene
enlaces a todas las demás páginas de documentación.
5.2.1 Visita Javadoc en Eclipse
Además de ver Javadoc como un conjunto de páginas externas, está integrado en
Eclipse. Puede ver la documentación contextual simplemente colocando el puntero
del mouse sobre el nombre de una clase o método (Fig. 5.7 ).
Si mueve el puntero del mouse sobre la ventana emergente, aparecerá una barra
de menú en la parte inferior que incluye opciones para ver Javadoc en una pestaña
" Vista de Javadoc " en la ventana. en el abajo de el pantalla, o abierto arriba el
Javadoc en a nuevo pestaña en el ventana del editor de código.
Si no desea depender de una conexión a Internet para acceder al Javadoc en
línea, puede vincular Eclipse a una versión descargada localmente. Para ello,
seleccione “ Preferencias ” en el menú “ Ventana ” . A continuación, en el
cuadro de diálogo “ Preferencias ” , seleccione “ Java ” y, a continuación, “ JRE
instalados ” . En el panel de la derecha, seleccione el JRE que esté utilizando
(puede que solo haya uno) y, a continuación, pulse “ Editar ”. botón. Este
voluntad llevar tú a el " Editar JRE ” diálogo, dónde tú poder seleccionar el
actual
5.5 Using 103
Javadoc
Higo. 5.7 Contexto – sensible Javadoc apareciendo en Eclipse
Ubicación de Javadoc, luego presione “ Ubicación de Javadoc …” botón, que lo
llevará al cuadro de diálogo donde puede seleccionar la ruta al archivo (debe
apuntar al archivo original, no a una carpeta extraída). Una vez que haya agregado
la ruta al archivo, asegúrese de agregar la ruta " docs/api " a la “ Ruta dentro del
archivo ” campo. Figura 5.8 muestra los distintos diálogos que intervienen en este
proceso algo complicado.
Higo. 5.8 Añadiendo Javadoc en el Eclipse ambiente
104 5 Creating
Objects
Ejercicio 5.4
• Crear a clase con a " principal " método.
• La clase Point dentro del paquete “ [Link] ” representa las coordenadas “ x ”
e “ y ” de a punto en a bidimensional espacio. En " principal " , crear a nuevo
Objeto java. [Link] que utiliza el constructor de argumentos cero. Agregue
la declaración “ im-port ” necesaria .
Nota
Si el módulo “ [Link] ” Si el archivo incluido cuando creó el proyecto por
primera vez está vacío, su código no se compilará y aparecerá el error “ No se
puede resolver la importación de [Link] ” . Esto se debe a que en el sistema de
módulos el paquete “ [Link] ” se encuentra en un módulo separado llamado “
[Link] ”. que no se carga de forma predeterminada. Hay dos soluciones
sencillas para esto:
1. Agregue manualmente “ requiere [Link] ” a su archivo
de información del módulo o
2. Haz clic derecho en tu proyecto Eclipse y selecciona “ Configurar ” - > “
Crear módulo - [Link] ” . Esto creará un nuevo archivo “ módulo - info ”
con todas las entradas requeridas. También agregará todos los paquetes en tu
proyecto como “ exportaciones ” . Esto significa que cualquier otro código
que haya usado tu módulo podría acceder a las clases en estos paquetes.
• Imprimir el Punto objeto en el consola usando “ [Link] ”: ¿qué son es
“ x ” y “ y ” coordinar ¿valores?
• Cambie ambos valores de coordenadas e imprímalo nuevamente (consulte el
Javadoc para obtener detalles sobre qué métodos se pueden usar para hacer
esto).
• Por qué hacer tú pensar el “ x ” y “ y ” campos de Punto objetos son
¿accesible al público ?
Ejercicio 5.5
Por razones que solo conocen los diseñadores de Java, la clase Date tiene un
método “ getTime ” eso devoluciones (como a largo entero) el número de
milisegundos eso tener desde el 1 de enero de 1970 en Greenwich Mean Time
(GMT). Podemos utilizar esto para calcular el actual tiempo por usando el dividir
(/) y resto (%) operadores. Él es no el más fácil forma de mostrando el tiempo (el
más nuevo clases en el “ [Link] ” paquete proporcionado a mucho Más simple
solución), pero sirve como a útil aritmética ejercicio. A Para evitar tener que sacar
la calculadora, se requieren las siguientes cifras:
• allá son 86.400.000 EM en a día
• allá son 3.600.000 EM en un hora
• allá son 60.000 EM en a minuto
Usar estos a escribir alguno código eso voluntad decir tú el actual tiempo.
5.3 Resumen 105
5.6 Resumen
Comenzamos este capítulo analizando la creación y el uso de algunos objetos y
métodos relacionados con datos de cadenas (Strings, StringBuilders, StringBuffers
y “ toString ”). método). Este era seguido por alguno importante asuntos acerca
de el La forma en que se hace referencia a los objetos en la memoria cuando se
programa con Java y la forma en que algunos operadores trabajan con objetos. El
recolector de basura de Java, que maneja la eliminación de no deseado objetos de
memoria, era también introducido. De nuevo, Se discutieron los objetos de cadena
en el contexto de la inmutabilidad y concatenación de cadenas.
La última parte del capítulo se ocupó de cuestiones sobre cómo se procesan los
objetos de paquetes distintos de “ [Link] ”. se puede utilizar en aplicaciones
Java, utilizando varias formas de importar clases y teniendo en cuenta los módulos
y la función del archivo “ [Link] ” .
El capítulo concluyó con una breve introducción a la documentación de
Javadoc que poder ser visto en línea o descargado y visto en a navegador (como
Bueno como (integrado en Eclipse) para ayudarle en la programación Java. Poder
hacer referencia el Javadoc es un básico herramienta cuando laboral con Java, y
nosotros voluntad referirse a Lo repetimos regularmente en el resto de este libro.
Creando Dominio Clases
6
En el anterior capítulo nosotros creado objetos de alguno de el comúnmente usado
clases En las bibliotecas de Java, incluidas las cadenas, las fechas y los puntos, sin
embargo, para crear un software útil, debemos ir más allá de estas clases de
biblioteca genéricas y reflejar las preocupaciones de nuestra propia aplicación.
dominios. En este capítulo, Comenzaremos a explorar cómo nosotros crear nuevo
dominio clases eso poder representar el objetos de interés a a nosotros en nuestras
propias aplicaciones.
6.1 Objeto Orientación y Dominio Objetos
La programación orientada a objetos se basa en una premisa simple: como seres
humanos, pensar de el mundo alrededor a nosotros como ser hecho arriba de
objetos, y eso software También puede estar formado por objetos. Por supuesto,
no es tan sencillo. Aunque podemos observar objetos del mundo real para
ayudarnos a comprender los conceptos clave de la orientación a objetos, también
debemos darnos cuenta de que los objetos en el software tienen sus propias
características. este capítulo nosotros voluntad comenzar por mirando en objetos y
su relaciones en el mundo real y luego ver cómo se pueden aplicar estas ideas a la
tarea de programación.
Un objeto del mundo real es algo que percibimos como que tiene una identidad
única (mi regla, eso lápiz etc.) y un existencia eso poder ser descrito en términos
de qué él es (un contundente media pensión lápiz con a masticado Goma puesta el
fin) y qué él hace (él Sorteos y En Zen y el arte del mantenimiento de la
motocicleta , Robert Pirsig dibuja un diagrama de su motocicleta que incluye tanto
sus componentes como sus funciones como diferentes aspectos del mismo objeto
(Fig. 6.1 ).
También observamos otras cosas sobre los objetos. Descubrimos que los
objetos individuales no son tan inusuales como para no tener mucho en común con
otros objetos de un tipo similar. Por ejemplo, podemos reconocer todos los tipos
de reglas como del tipo “ regla ” . incluso aunque ellos puede ser diferente
longitudes, tener diferente medición escalas y ser hecho de diferente materiales.
Nosotros también nota eso objetos son no mucho usar en
© Saltador Naturaleza Suiza Estado 2020
107
D. Parsons, Foundational Java , Textos en Ciencias de la
Computación, [Link]
108 6 Creating Domain
Classes
Motor Cycle
Components Functions
Higo. 6.1 A motocicleta objeto incluye ambos es componentes y es funciones
su propio. A gobernante, a ser útil, debe interactuar con otro objetos (semejante
como gente y lápices) para medir o dibujar una línea.
A explorar estos ideas más nosotros voluntad usar el ejemplo de a reloj, cual
tiene la ventaja de ser un objeto que cubre la brecha entre el mundo real y la
programación. Como Bueno como ser rodeado por relojes de diferente tipos en
nuestro Vida cotidiana, nosotros son también frecuentemente bombardeado por
relojes en software, desde ellos aparecer En un tranquilo esquina de muchos
aplicaciones. Primero, nosotros voluntad mirar en alguno aspectos de relojes
del “ mundo real ” .
6.1.1 Reloj Objetos en el Real Mundo
Tome un reloj y descríbalo. Podría ser un reloj de pared con una esfera redonda y
tres manecillas. Digamos que tiene una esfera blanca, con manecillas de horas y
minutos negras y un segundero rojo. Todo esto es una descripción de lo que es un
reloj, o su " estado " . Algunos aspectos del estado de un reloj no serán tan
obvios para nosotros. En un reloj que funciona con pilas, por ejemplo, el nivel de
cargar en el batería hace no convertirse evidente hasta el reloj se detiene. El estado
de un objeto está representado por sus atributos o campos .
También tiene “ comportamiento ” que es lo que hace el reloj. El
comportamiento más importante (posiblemente el único) de un reloj es decirnos la
hora. Otros comportamientos posibles de los relojes podrían incluir decirnos la
fecha o hacer sonar una alarma. El estado y el comportamiento están muy
relacionados, como podemos ver si consideramos que el estado del reloj en
cualquier momento incluye la hora que está mostrando. De manera similar, el
comportamiento de una alarma reloj eso permite él a anillo es relacionado a es
estado de zumbido. El comportamientos que un objeto puede realizar se conocen
como sus operaciones o métodos . Figura 6.2 muestra un diagrama de clases
utilizando unificado Modelado Notación en lenguaje (UML) que muestra Algunos
atributos y operaciones de un objeto de reloj. En este tipo de diagrama, un
rectángulo se divide en tres partes, y la sección superior contiene el tipo de objeto
(el nombre de la clase), el sección media el nombres de el campos y el abajo parte
el nombres de los métodos.
6.1 Objeto Orientación y Dominio Objetos 109
Higo. 6.2 Lenguaje
unificado de modelado clase
Diagrama de un reloj, con Clock
algunos campos y métodos.
currentTime
alarmState
getTime
setTime
setAlarm
turnAlarmOff
6.1.2 Encapsulación y Información Ocultación
Un objeto “ encapsula ” tanto el estado como el comportamiento, uniéndolos en un
todo coherente. entero. Este encapsulamiento trae juntos el público interfaz de un
objeto (la cara que presenta al mundo exterior) con elementos privados que forman su
representación interna. Parte de esta unión del estado y el comportamiento de un
objeto es el capacidad para esconder mucho de el funcionamiento interno de un
objeto. Nosotros necesidad Para ver el rostro de el reloj, pero nosotros hacer no
necesidad a saber cómo él obras. Nosotros podría Necesita interactuar con él de otras
maneras, como cambiar la batería o darle cuerda a un reloj. mecanismo en un
antigüedad reloj, pero nosotros aún hacer no necesidad a saber cómo Funciona
internamente para utilizarlo. Esta característica de los objetos se llama “ ocultación de
información ”. y ayuda a simplificar el edificio de software sistemas porque él se
esconde Lo que no necesitamos saber, lo que nos permite centrarnos en los aspectos
importantes de un objeto . personaje. De este modo, un objeto muestra el mundo solo
eso cual el mundo necesita ver. Este es bastante como a compañía o otro organización
eso tiene alguno regiones de su funcionamiento que proporciona su imagen pública,
por ejemplo, un sitio web de compras en línea, y otras partes que proporcionan
servicios puramente internos como intranets de la empresa, sistemas de gestión de la
cadena de suministro, etc. (Fig. 6.3 ).
6.1.3 Objeto Identidad
Somos capaces de reconocer que dos objetos que parecen iguales tienen una
identidad diferente. Si nosotros pararse próximo a a producción línea mirando
cientos de idéntico los relojes van por, nosotros saber eso ellos son todo individual
objetos. Él puede ser eso el interno Estado de todo estos relojes es el mismo. Para
ejemplo, término análogo relojes y relojes (es decir Los relojes con manecillas
suelen venderse con las manecillas apuntando a las diez y diez para indicar el
nombre del fabricante . Aun así, sabemos que son objetos diferentes porque
ocupan un espacio diferente en un momento dado. Sin embargo, también sabemos
que todos estos relojes son del mismo tipo, pertenecen a la misma clase . En cierto
nivel, entonces, clasificar objetos significa reconocer que todos los objetos
idénticos pertenecen a una sola clase.
110 6 Creating Domain
Classes
private implementation
Buy
manufacture
stuff!
administration
Higo. 6.3 Información ocultación medio eso nosotros solo necesidad a ver el público interfaz
de un objeto, no su implementación interna
6.2 Creando Nuevo Clases
Teniendo introducido alguno conceptos de el real mundo, nosotros voluntad ahora
traer nuestro centrarse de nuevo a Java programación. Edificio orientado a objetos
sistemas medio creando clases que reflejarán las preocupaciones específicas de
los diferentes dominios de aplicación. En esta sección, trabajaremos con una clase
de ejemplo que representa los cursos ofrecidos por una empresa de capacitación.
El “ Curso ” La clase no pretende representar una entrega específica de un curso,
sino que define un curso sobre un tema práctico que puede ofrecerse varias veces
en diferentes ubicaciones por diferentes instructores.
Aunque no es realmente útil pensar en las clases como simples contenedores de
datos, porque métodos de un objeto son es mayoría importante característica, él es
útil a comenzar afuera De esta manera se puede ver cómo se construye una clase,
especialmente en Eclipse. El diagrama de clases UML de la figura 6.4 muestra que
la clase Curso tiene tres campos: el nombre del curso, el duración de el curso (en
días) y el precio (por persona). Más tarde nosotros Agregará los métodos.
En el pasado ejemplos, nosotros tener visto como Para crear a clase con una "
principal " método, pero una clase que debe actuar como un objeto de dominio no
tiene un método “ main ” , ya que representa un tipo de objeto de dominio en
lugar de un punto de entrada a un programa. Por lo tanto, para crear una clase “
Course ” en Eclipse desmarcaríamos la opción para crear un método “ main ”
(Fig. 6.5 ).
6.2 Creating New 111
Classes
Curso
nombre
numeroDeDías
precioPorPerso
na
métodos…
Higo. 6.4 El campos de el Curso clase
Higo. 6.5 Creando a dominio clase en Eclipse (sin a principal método)
112 6 Creating Domain
Classes
Como nosotros sierra en el anterior capítulos, dónde nosotros creado clases que
contiene Métodos “ principales ” , una clase Java se declara utilizando la palabra
clave “ clase ” , seguida del nombre de el clase (cual por convención usos Pascal
caso) y el apertura abrazadera de la definición de clase. Las clases que son
generalmente visibles para otras clases también se declaran “ públicas ” . El
comienzo de la definición de clase para Course, generada por Eclipse, se ve así
(crear una clase sin método “ principal ” generará solo un cuerpo de clase vacío):
público clase Curso {
6.2.1 Añadiendo Campos a a Clase
Dentro de este cuerpo de clase, comenzaremos agregando los campos de datos. A
diferencia del método “ main ” , que tiene visibilidad pública, los campos suelen
estar marcados como “ privados ” . Este acceso modificador especifica eso el
datos campos son solo accesible de dentro objetos de la clase; no son visibles para
otros objetos. Esto es parte de la encapsulación y ocultación de información que
presentamos anteriormente en este capítulo. Protegemos los objetos internos
estado de un objeto de ser arbitrariamente cambió por Otras partes de a programa.
Para la clase Curso, agregaremos los tres campos que se muestran en la Fig. 6.4 .
Los campos se declaran privado, y el " nombre " campo voluntad ser a Cadena, el
“ númeroDeDías ” un int, y el “ precio por persona ” a doble. A privado El
atributo es Todavía visible para cualquier método de la misma clase, por lo que
cualquier método de un Curso podrá acceder a estos campos.
Las declaraciones de campos se agregan directamente al cuerpo de la clase, no
dentro de ningún método. A diferencia de las variables declaradas dentro de un
método, los campos no tienen que inicializarse explícitamente. Cuando se crea un
objeto de la clase, cada uno de los valores de los atributos voluntad ser dado el por
defecto valor para eso tipo; cero para numérico tipos y null para tipos de
referencia (como cadenas). Los campos booleanos tienen como valor
predeterminado “ falso ” .
público clase Curso
{
cadena privada nombre;
privada entero
numeroDeDias;
privado doble precioPorPersona;
}
A pesar de campos tener por defecto valores, nosotros poder asignar otro valores si
nosotros desear, o
simplemente ayuda el legibilidad de el código por explícitamente declarando el
inicial valor de a campo, por ejemplo,
6.2 Creating New 113
Classes
público clase Curso
{
cadena privada nombre = nulo;
privada entero numeroDeDías =
0;
privado doble precio por persona = 0.0;
}
6.2.2 Añadiendo Métodos a a Clase
Teniendo agregado el campos a el clase, nosotros necesidad a proporcionar alguno
métodos entonces eso Otras partes de nuestro código pueden interactuar con los
objetos Course. Los tipos de métodos más simples son los “ getters y setters ” ,
que permiten acceder a los campos de forma controlada. Los métodos de una clase
también aparecen dentro del cuerpo de la clase, pero estos suelen declararse con “
public ”. visibilidad porque proporcionan la interfaz pública para el objeto.
Primero, nosotros voluntad mira a el creación de una “ captador ” método que
permite el nombre de Un objeto de curso al que se debe acceder. Un método getter
debe devolver un valor al código que llamado el método. " devolver " es Java
palabra clave eso es requerido en cualquier método que devuelve un valor (es
decir, cuando el tipo de retorno del método es no “ vacío ” , cual significa que no
se devuelve ningún valor). La palabra clave “ return ” va seguida del nombre de
la primitiva valor o objeto ser regresó, cual en este caso es el " nombre " campo.
Cualquier método eso devoluciones a valor debe incluir el tipo de eso devuelto
valor como parte de su declaración. En este caso, a Cadena es ser regresó,
entonces el método definición comienza con este tipo, seguido del nombre del
método y la lista de parámetros entre paréntesis. No hay argumentos de
parámetros para este método, por lo que los paréntesis están vacíos:
público Cadena obtenerNombre()
{
devolver nombre;
}
Nota
Una sentencia de retorno es la última línea de un método que se ejecuta, incluso
si no es la última línea de código del método. Las líneas que aparecen después de
una sentencia de retorno se ignorarán. Ocasionalmente, podemos utilizar este
enfoque para acortar la ejecución de un método, de forma similar a como lo
podemos hacer con una sentencia " break " .
El segundo método nosotros voluntad agregar es el pareo “ establecedor ” eso
poder colocar el valor del " nombre " campo. En orden a hacer este nosotros tener
a aprobar a Cadena parámetro argumento a
114 6 Creating Domain
Classes
el método, que contiene el nombre que se va a configurar, por lo que se debe
proporcionar el tipo de este parámetro, a lo largo de con a local nombre eso
voluntad ser usado a referirse a este parámetro en el cuerpo del método. El nombre
local del parámetro puede ser el mismo que el nombre del campo, pero si este es el
caso, la referencia al campo debe ir precedida de la palabra clave “ this ” , para
especificar que se refiere al campo en el objeto “ this ” , no al parámetro local. El
tipo de retorno del método es “ void ” , lo que significa que no devuelve ningún
valor. Aquí está el método:
público vacío setName(Cadena nombre)
{
[Link] = nombre;
}
Nota
El compilador no podrá ayudarle a utilizar “ this ” para desambiguar los
nombres de los campos y de los parámetros locales. Es
perfectamente legal escribir el método de esta manera:
público vacío setName(Cadena nombre)
{
nombre = nombre;
// asigna el valor de el local parámetro argumento "nombre"
// a sí mismo y hace no colocar el campo ¡valor!
}
Sin embargo, el efecto de este es a ignorar el campo de el objeto y simplemente
colocar el Valor del parámetro en sí mismo. ¡Algo a tener en cuenta!
La creación de métodos getters y setters es un requisito tan básico que Eclipse
proporciona una herramienta para generar estos métodos a partir de campos.
Simplemente seleccione “ Generar métodos getters” y Los setters de el Menú “
Fuente ” . Este voluntad mostrar el diálogo en la figura 6.6 . Este diálogo
voluntad lista todo el adquiridor y métodos de establecimiento que tienen no Ya se
han creado para los campos de la clase. En la Fig. 6.6 El captador y el definidor
para el atributo “ nombre ” ya se han escrito manualmente, por lo que solo se
pueden usar métodos para “ númeroOfDays ”. y “ precio por persona ” son aún
disponible para selección. Nota eso el nuevos metodos voluntad ser agregado en el
actual cursor posición (este es indicado en el diálogo) así que asegúrese de haber
posicionado el cursor en el lugar correcto antes de generar estos métodos.
Si nosotros escribir o generar captadores y establecedores para todo el campos
de el Curso clase, El código se verá así:
6.2 Creating New 115
Classes
Higo. 6.6 Seleccionando métodos a ser generado de campos en el " Generar Captadores y
Diálogo de “ Setters ”
116 6 Creating Domain
Classes
paquete [Link].capitulo6;
público clase Curso
{
cadena privada nombre;
privada entero
numeroDeDias;
privado doble precioPorPersona;
público Cadena
obtenerNombre()
{ devolver nombre;
}
público vacío setName(Cadena nombre)
{ [Link] = nombre;
}
público entero
obtenerNumeroDeDías() {
devolver numeroDeDías;
}
público vacío establecerNumeroDeDías(int Número de días) {
este.númeroDeDías = númeroDeDías;
}
público doble
obtenerPrecioPorPersona() {
devolver precioPorPersona;
}
público vacío establecerPrecioPorPersona(doble
precioPorPersona) { [Link] =
precioPerPerson;
}
}
A prueba el lo esencial de este clase antes desarrollo él más, nosotros voluntad
necesidad a método “ main ” para crear un objeto de la clase Course e invocar sus
métodos. que poner este " principal " método en el Curso clase, cual quería
confundir El papel de el clase como ser ambos a dominio clase y a programa
entrada punto, él es Es mejor crear una clase separada para alojar el método “
principal ” .
Esta clase de ejemplo se llama CourseRunner y contiene un método “ main ” .
“ Course ” representa una clase de dominio, pero “ CourseRunner ” es solo un
punto de entrada al programa. Tal como lo hemos hecho con las clases de la
biblioteca Java, creamos un nuevo objeto llamando a el constructor método y usar
el " punto " operador a invocar a método de El objeto.
6.2 Creating New 117
Classes
paquete [Link].chapter6;
clase pública CourseRunner
{
público estático vacío principal(Cadena[] argumentos)
{
Curso javaCourse = new Course();
[Link]("Java");
[Link](3);
[Link](1000.0);
[Link]([Link]() +
" curso dura " + [Link]() +
" días y costos " + [Link]());
}
}
El producción de este programa es:
Java curso dura 3 días y costos 1000.0
6.3 Constructores
Una cosa que puede resultarle extraña del ejemplo anterior es que pudimos crear
un nuevo objeto Course llamando a un constructor, pero nunca definimos un
método constructor. Esto se debe a que hay un constructor predeterminado (cero
argumentos) disponible. para cada clase. Cualquier clase eso tú crear voluntad
tener este por defecto Constructor disponible. Esto es útil, pero su limitación es
que el constructor predeterminado no puede inicializar explícitamente el estado de
un nuevo objeto, ya que no acepta ningún parámetro como argumento.
Para superar esta limitación, podemos crear nuestros propios constructores, y
estos constructores poder llevar parámetro argumentos. Para ejemplo, nosotros
podría desear a crear un constructor que puede tomar tres argumentos de
parámetros para establecer los valores iniciales de los tres campos. Este poder ser
agregado a el clase cuerpo como el captadores y establecedores nosotros ya se han
añadido. El constructor, a diferencia de otros métodos, no tiene un tipo de retorno
especificado (el actual devolver tipo es siempre un objeto de el clase). Él siempre
tiene el mismo nombre como la clase, por lo que el constructor “ Course ”
también se llamará “ Course ” . En este constructor de ejemplo, se especifican los
tres argumentos de parámetro y en el cuerpo del método los campos se configuran
para que sean iguales a los valores de parámetro.
público Curso(Cadena nombre, entero días, doble precio)
{
[Link] = nombre;
[Link] = dias;
[Link] =
precio;
}
118 6 Creating Domain
Classes
A tal vez inesperado lado efecto de este es eso si tú agregar este constructor a
su clase, encontrará que la clase CourseRunner ya no se compila, porque la
siguiente línea ahora tiene un error:
Curso Curso de Java = nuevo Curso();
Este problema es causado por el hecho eso el por defecto constructor es solo
disponible Si no especifica ninguno de sus propios constructores, ahora que hemos
creado un método constructor, el predeterminado ya no se podrá utilizar.
6.3.1 Sobrecargado Constructores
Afortunadamente, es posible tener más de un constructor, lo que evita el problema
de perder el uso del constructor predeterminado. Esto es posible mediante la
técnica de sobrecarga, que tenemos visto previamente, dónde el mismo metodo
nombre puede se puede utilizar con diferentes combinaciones de argumentos de
parámetros. Funciona proporcionando múltiples Implementaciones de el método,
cada uno teniendo a diferente combinación de tipos y/o números de argumentos de
parámetros. Es posible que queramos tener cero argumentos constructor como
Bueno como el uno eso acepta tres parámetros, a dar usuarios del clase más
Opciones acerca de cómo ellos crear nuevo Curso objetos. A ilustrar Para
aprovechar esta posibilidad, agregamos otro constructor que no toma parámetros
como argumentos. Este constructor establece los valores de los campos en valores
predeterminados razonables.
público Curso()
{
[Link] = "Sin nombre Curso";
[Link] = 3;
[Link] = 1000.0;
}
público Curso (Cadena nombre, entero días, doble precio)
{
[Link] = nombre;
[Link] = dias;
[Link] =
precio;
}
Nosotros poder ahora crear objetos usando el parametrizado constructor. El
Se llama a la versión correcta del constructor en función de su firma.
Curso do = nuevo Curso("C#", 2, 1500,00);
6.3 Constructores 119
6.3.2 Encadenamiento Constructores
Un desgraciado lado efecto de añadiendo un adicional constructor en el ejemplo
arriba esta eso nosotros tener alguno bastante feo duplicación de código entre el
dos constructores, cada uno de a ellos Asignación valores a el tres campos.
Teniendo duplicado código como este es un problema de mantenimiento continuo
y es mejor evitarlo. El peligro con el código duplicado es que con el tiempo se
actualiza en un lugar pero no en otro. La solución a este problema es utilizar una
técnica llamada encadenamiento de constructores, que es donde un constructor
llama a otro constructor de la misma clase para implementar su funcionalidad. La
sintaxis para hacer esto utiliza la palabra clave " this " , pero de una manera
ligeramente diferente a cómo hemos visto que se usa " this " antes. En el caso de
los constructores, puede llamar a uno desde otro utilizando el siguiente enfoque.
público Curso()
{
esto("Sin nombre Curso", 3, 1000.0);
}
público Curso(Cadena nombre, entero días, doble precio)
{
// inicialización código usando parámetros…
}
El uso de “ this( … ) ” llama a otro constructor con argumentos de parámetros
coincidentes, entonces el cero argumentos constructor voluntad llamar el tres
argumentos constructor, eliminando la duplicación de código y haciendo que la
clase sea más robusta en el contexto de cambios futuros.
6.3.3 Interno Encapsulación en Constructores
Él es importante eso a clase debería no exponer es objetos ' estado (es decir es
campos) directamente a los clientes, por lo que hemos utilizado campos privados,
encapsulados dentro de la clase, pero también proporcionamos un conjunto de “
captadores ” y " setter " Métodos a través de los cuales se puede manipular
el estado de un objeto . Aunque todavía no hemos ido más allá de la simple
obtención y configuración de valores de campo, la implementación de estos
métodos puede proteger el estado de un objeto de volverse inconsistente.
Debido a que estos métodos pueden incluir funcionalidad más allá de la simple
obtención y configuración de valores, es una buena idea utilizar los métodos
getter. y establecedores incluso dentro el clase sí mismo, como en este
versión de el constructor de tres argumentos.
público Curso (Cadena nombre, entero días, doble precio)
{
setName(nombre);
setNumberOfDays(días);
setPricePerPerson(precio);
}
120 6 Creating Domain
Classes
Esta encapsulación interna se vuelve importante si, por ejemplo, agregamos
algunas condiciones de protección a los métodos de establecimiento para evitar
que se establezcan en valores inapropiados. Por ejemplo, podríamos restringir el
valor de “ numberOfDays ” atribuir a a positivo entero en el rango 1 – 10 o
aplicar alguno otro negocio regla acerca de cuántos días a El curso debería ser
capaz a último. Aquí es a levemente actualizado versión de El método eso asegura
eso el “ númeroDeDías ” poder solo ser colocar dentro el rango 1 –
10. Valores afuera eso rango son ignorado.
público vacío establecerNumeroDeDías(int Número de días)
{
si(numeroDeDias >= 1 && numeroDeDías <=10)
{
[Link] = numeroDeDias;
}
demás
{
// hacer no aceptar el parámetro valor
// debería probablemente tirar un excepción (ver Cap. 9)
}
}
Al restringir nuestro acceso al campo “ numberOfDays ” únicamente dentro
del método setter, podemos garantizar que este código condicional siempre se
aplique cuando se establece el valor del campo, incluso desde dentro de la clase
misma.
Nota
En este ejemplo, simplemente ignoramos el valor del parámetro si está fuera del
rango aceptable. Lamentablemente, esto no ayuda a señalar los problemas al
código que envió el valor inaceptable. En el capítulo 9 , veremos cómo generar
una excepción si ocurre este tipo de problema, de modo que el conocimiento de lo
que sucedió se pueda propagar a otras partes del programa.
6.4 Acceso Modificadores
Como hemos visto en nuestros ejemplos hasta ahora, los modificadores de acceso
se utilizan para controlar el acceso. a clases, constructores, campos y métodos.
Como a general pauta, Los atributos son marcado como privado, y clases,
constructores y métodos marcado como público, pero esto es por No medio a
universal regla. Para ejemplo, no todo métodos debería ser público. Tome una
clase que represente una cuenta bancaria. Puede tener un método “
setAccountBalance ” . Este puede ser útil adentro el clase, pero él es
probablemente no sensitivo a hacer
6.4 Acceso Modificadores 121
Mesa 6.1 Visibilidad modificadores
Visibilidad modificador Significado
Público Visible de en cualquier lugar eso tiene acceso a través de el ruta de
clase
Privado Accesible solo dentro el clase sí mismo
<predeterminado> Visible dentro el clase y también a lo largo de el paquete
(No modificador palabra
clave utilizada)
Protegido Visible dentro el clase, a lo largo de el paquete, y a subclases En otros
paquetes
Es público. Los cambios externos al saldo actual de una cuenta solo se deben
realizar a través de una transacción válida, no de manera arbitraria. Por lo tanto, a
veces descubrimos que escribimos métodos solo para implementación interna y
estos se marcarán como " privados ".
Ocasionalmente, los campos son públicos. Existen varias razones por las cuales
esto podría ser así. Una es que son campos finales . Dado que un campo marcado
como “ final ” En Java no se puede cambió una vez es valor tiene estado colocar,
allá es No peligro en exposición él como a campo público. Por ejemplo, la clase
Math (que hemos utilizado para generar un número aleatorio) tiene un campo
público llamado “ PI ”. (que representa el valor de p ), que no se puede cambiar.
La clase Point tiene los campos “ x ” y “ y ” , que son públicas en parte como
resultado de ser " legado " código de a muy primero versión de Java, pero
también (pendiente a algunos cambios posteriores) Habilítanos a recuperar el
valores de el campos como enteros, cuando los métodos “ get ” los devuelven
como dobles. Esta es una variación interesante de la sobrecarga, desde
normalmente sobrecarga poder solo ser hecho por parámetro liza, no a vuelta de
correo tipos. Este medio eso nosotros no puedo diferenciar dos métodos de el
mismo Nombre por el devolver tipos. El público campos en el Punto clase dar a
nosotros a amable de solución alternativa a ese problema que al menos puede
evitarnos realizar una conversión innecesaria de un doble a un int.
Hasta ahora sólo hemos hablado de lo “ público ”. y “ privado ” acceso, pero
hay cuatro visibilidad modificadores en Java, incluido el menos usado (pero a
veces útil) “ predeterminado ” y “ protegido ” visibilidades. Tabla 6.1 resume el
cuatro modificadores de visibilidad. Veremos algunos ejemplos de aplicación del
“ predeterminado ” y “ protegido ” modificadores en los siguientes capítulos.
6.5 Javadoc y código Comentarios
En el capítulo anterior, vimos cómo se puede descargar la documentación de
Javadoc para las clases de la biblioteca estándar de Java y vincularla a Eclipse.
También podemos usar la documentación de Javadoc documentación herramienta
a crear nuestro propio documentación, desde él es enviado
122 6 Creating Domain
Classes
con el Kit de herramientas JDK (tú voluntad encontrar el “ javadoc ” solicitud en
el " papelera " carpeta de el Instalación de JDK). La documentación de sus
propias clases se creará como un conjunto de páginas HTML con hipervínculos,
utilizando la misma estructura y formato que el Javadoc estándar. Cuando genera
documentación con Javadoc, se extrae la información básica sobre las clases,
como los nombres de sus campos y métodos. Ya hemos presentado la sintaxis para
escribir comentarios en bloque que se incluirán en el Javadoc.
/**
documento javadoc comentarios a explicar su clases y métodos
*/
Hay una serie de símbolos que podemos utilizar dentro de estos bloques de
comentarios para ayudar a aumentar la cantidad de información incluida en el
Javadoc generado, por ejemplo, algunas etiquetas HTML (como el simple “ <br/>
” para un salto de línea o “ <hr/> ” para una regla horizontal) y ciertas palabras
clave precedidas por el carácter “ @ ” , incluyendo:
@autor (a espectáculo el del autor nombre)
@version (a espectáculo el versión número de el clase)
@param (para dar la oportunidad de explicar los significados de los
parámetros de un método)
@return (a espectáculo el devolver tipo de el método)
Mayoría de estos poder ser generado automáticamente por Eclipse dónde ellos
son relevante. Simplemente coloque el cursor en un elemento de código y
seleccione “ Generar comentario de elemento ” en el menú “ Fuente ” . Esto
agregará un bloque de comentarios y las etiquetas “ @ ” relevantes , a las que
puede agregar texto explicativo adicional.
Hay muchos otros aspectos de la sintaxis de Javadoc que no se tratan aquí, pero
hay información completa disponible en el sitio web de Oracle.
A continuación se incluye la clase completa del curso, incluidos varios
comentarios de estilo Javadoc. detallado Javadoc estilo de comentando es no
usado más allá de este capítulo, pero Por supuesto, puedes usarlo en todo tu
código si lo deseas. Incluso sin ninguna de estas sintaxis, Javadoc poder crear
alguno útil documentación de su clases semejante como detalles de constructores,
campos y métodos.
6.5 Javadoc and Code 123
Comments
paquete [Link].capitulo6;
/**
* El Curso clase representa a capacitación curso definición,
* no un individual entrega de el curso
* @autor David Párrocos
*
*/
público clase Curso
{
cadena privada nombre;
privada entero
numeroDeDias;
privado doble precioPorPersona;
/**
* cero argumentos constructor
*/
público Curso()
{
esto("Sin nombre Curso", 3, 1000.0);
}
/**
* Parametrizado constructor
* @param nombre El nombre de el curso
* @param días El longitud de el curso en días
* @param precio El costo de el curso por persona
*/
público Curso(Cadena nombre, entero días, doble precio)
{
setName(nombre);
setNumberOfDays(días);
setPricePerPerson(precio);
}
/**
* @devolver El nombre de el curso
*/
público Cadena
obtenerNombre()
{ devolver nombre;
}
/**
* @param nombre El nombre de el curso
*/
público vacío setName(Cadena nombre)
{ [Link] = nombre;
124 6 Creating Domain
Classes
}
/**
* @devolver El longitud de el curso
*/
público entero
obtenerNumeroDeDías() {
devolver numeroDeDías;
}
/**
* @param numeroDeDías El número de días el curso dura
*/
público vacío establecerNumeroDeDías(int Número de días) {
if(númeroDeDías >= 1 && númeroDeDías <=10)
{
[Link] = numeroDeDias;
}
demás
{
// hacer no aceptar el parámetro valor
// debería probablemente tirar un excepción
}
}
/**
* @devolver El precio de el curso por persona
*/
público doble
obtenerPrecioPorPersona() {
devolver precioPorPersona;
}
/**
* @param precio El precio de el curso por persona
*/
público vacío establecerPrecioPorPersona(doble precio) {
[Link] = precio;
}
}
6.5.1 Creando Javadoc en Eclipse
Para generar su propia documentación desde Eclipse, debe configurar la ubicación
de la carpeta de salida donde se generarán los archivos (debe ser una ubicación
diferente a la descarga estándar de Javadoc). Para ello, seleccione “ Propiedades ”
en la opción de menú “ Proyecto ” en la barra de menú principal. Esto mostrará la
carpeta “ Propiedades ” diálogo (Higo. 6.7 ). Seleccionar “ Javadoc Ubicación "
de el lista de Opciones a la izquierda del cuadro de diálogo y luego navegue hasta
la ubicación de salida elegida para configurar el " Javadoc ubicación camino " .
Sin embargo, ser cuidadoso no a elegir cualquier carpetas con espacios
6.5 Javadoc and Code 125
Comments
Higo. 6.7 Configuración el Javadoc ubicación en el Proyecto ' s " Propiedades " diálogo
en el nombre o esto puede causar problemas. Puede presionar el botón “ Validar ”
para asegurarse de que Javadoc se pueda escribir en esa ubicación.
A generar Javadoc, seleccionar " Generar Javadoc ” de el " Proyecto " opción
en La barra de menú principal. Esto abrirá la “ Generación de Javadoc ” diálogo
(Fig. 6.8 ). En este diálogo, puede simplemente hacer clic en “ Finalizar ” o
configure la salida usando este diálogo y los que siguen (usando el botón “
Siguiente ” ). Ya que puede regenerar su Javadoc con la frecuencia que desee,
siempre puede experimentar con estas configuraciones y cambiar la configuración
de salida más tarde si lo desea.
Nota
Si la ruta a “ [Link] ” Si Eclipse no lo encuentra automáticamente, deberá
configurar la ruta presionando el botón “ configurar ”. botón junto al campo de
texto “ Comando Javadoc ” , luego busque el archivo “ [Link] ” en
la carpeta “ bin ” de su instalación JDK.
Al hacer clic en el botón “ Finalizar ” en el cuadro de diálogo “ Generar
Javadoc ” , la documentación se generará en la carpeta de salida que haya elegido.
Si navega hasta esa carpeta, podrá abrir la página “ [Link] ” en un navegador
web. Figura 6.9 muestra parte de una de las páginas HTML generadas por
Javadoc que se visualizan en un navegador.
126 6 Creating Domain
Classes
Higo. 6.8 El " Generar Javadoc ” diálogo. El Javadoc dominio poder ser encontró en el "
papelera " Carpeta de su instalación de JDK
6.5.2 Correr Javadoc de el Dominio Línea
Si tú desear a correr documento javadoc de el dominio línea, bastante que de
dentro Eclipse, tú simplemente tipo “ javadoc ” en el dominio línea seguido por el
nombre de a Java archivo, p. ej.
documento javadoc [Link]
Este ejemplo asume eso el Java archivos son en el actual carpeta. Tú
puede generar Javadoc para todas las clases en una carpeta usando un comodín,
por ejemplo,
documento javadoc *.Java
Tú debería encontrar eso el HTML páginas son escrito por por defecto a
el mismo directorio como su fuente archivo(s). De nuevo, tú poder carga el “
í[Link] ” archivo en a
6.5 Javadoc and Code 127
Comments
Higo. 6.9 Secciones de uno de el HTML páginas generado por Javadoc ser visto en a
Navegador web
navegador a ver el documentación. A conseguir el más completo información
posible escrito mediante Javadoc, podemos agregar algunas opciones, precedidas
por guiones, al comando “ javadoc ” , por ejemplo,
documento javadoc -privado -autor -versión *.Java
La primera opción ( “ -private ” ) garantiza que todos los atributos y métodos,
ya sean privados o público, son escrito a el producción archivos. El otro Opciones
( " -autor " y " - versión " ) Asegúrese de que cualquier “ @autor ” y “ @version
” entradas También aparecen en el archivo. Para ver todas las opciones posibles
(hay muchas), simplemente escriba “ javadoc ”. en el símbolo del sistema y se
enumerarán.
Ejercicio 6.1
• Crear el Curso clase con es atributos, métodos y constructores
• Cree una clase de prueba independiente con un método principal que crea una
instancia de la clase y ejercita sus métodos
• Agregar a “ máximo de participantes ” atributo con adecuado captadores y
establecedores
• Agregar a nuevo constructor eso acepta cuenta de su nuevo atributo
• Modificar su “ establecerMáximoDeParticipantes ” método a asegurar el
consistencia de El estado del objeto
• Actualizar su principal método a prueba su nuevo constructor y métodos
• Generar alguno Javadoc para su clase
128 6 Creating Domain
Classes
6.6 Tipos de Método
No todo métodos son justo simple “ captadores ” y “ configuradores ” . En
efecto, si ellos eran, Las clases serían muy aburridas. Otros tipos de métodos que
son útiles incluyen cálculos, consultas más complejas que los captadores
relacionados con campos y comandos. Ejemplos de cálculos métodos en el Curso
clase podría ser calculador descuentos, ganancia márgenes, etc. Las consultas
sobre el curso pueden estar relacionadas con entregas pasadas o futuras del mismo.
Curso (desde el Curso clase hace no sí mismo representar a curso entrega — esta
quería requerir Los comandos son cualquier cosa del tipo “ haz esto ” , por
ejemplo, se le puede pedir a una clase que escriba el esquema de su curso en un
archivo.
Figura 6.10 muestra a Lenguaje unificado de modelado diagrama eso incluye
alguno posible métodos para la clase Course además de sus métodos get y setter.
Hay otra clase en este diagrama, “ CourseDelivery ” , con algunos campos
sugeridos. Estas dos clases están asociadas, lo que significa que un objeto de una
clase puede comunicarse directamente con objetos de otra (esto se indica mediante
la línea continua entre las dos clases). El símbolo de asterisco significa “ muchos
” , es decir, un curso puede tener muchos envíos de cursos asociados a él.
Veremos la asociación con más detalle en el próximo capítulo.
Ejercicio 6.2
Agregar a nuevo método a el Curso clase con este firma:
público doble costoporpersonadescontado(int Porcentaje de descuento)
No es necesario agregar ningún campo nuevo a la clase para que esto funcione,
ya que solo necesita basar su cálculo en el campo “ costPerPerson ” existente.
Este método debería calcular cómo mucho él costos para a partícipe a
inscribirse en el curso si se aplica un descuento de oferta especial. Tenga en cuenta
que toma un valor “ int ” como argumento de parámetro y devuelve un valor “
double ” (calculado dentro del método).
Usar alguno código en a " principal " método a intentar afuera su “ costo por persona
con descuento ”
método y entonces regenerado su Documento Java.
Ejercicio 6.3
Este es un ejercicio de diseño, no uno que requiera que escribas código. Puedes
dibujar tus sugerencias usando diagramas de clases UML.
Curso Impartición del
* curso
Fecha de inicio
getScheduledDeliveries(ubicación) Fecha de
calculateDiscount(asistentes) finalización
writeCourseOutline(archivo) Ubicación
6.5 Javadoc and Code 129
Comments
Higo. 6.10 Más métodos de El curso clase, y un asociación con muchos Objetos de
CourseDelivery
6.6
130 Tipos de Método 6 Creating Domain129
Classes
• Qué podría a más completo diseño para el Impartición del curso clase mirar ¿como?
• Qué otro atributos podría él ¿tener?
• Actualmente el diagrama en Higo. 6.10 muestra No métodos. Qué métodos,
aparte ¿A partir de getters y setters, podría ser apropiado para un
CourseDelivery?
• Nosotros tener sugerido el Curso y Impartición del curso clases podría ser
asociado. ¿Puedes sugerir otras clases que puedan ser relevantes para este
dominio y que puedan estar asociadas con las clases Course o CourseDelivery?
6.7 Clase Reutilizar
En nuestro desarrollo de las diversas características de la clase Course, hemos
visto cómo la programación orientada a objetos nos permite modelar los objetos
del mundo real de un dominio. en software. Otro de el ventajas de
encapsulamiento en Un lenguaje orientado a objetos como Java es la
reutilización de código. En los capítulos 3 y 4 y 4 Vimos más de un ejemplo en el
que simulamos el lanzamiento de un dado generando y manipulando a aleatorio
número. En cada caso nosotros tenía a repetir el mismo código. Si Podemos
encapsular este código en un objeto “ Die ” , podemos reutilizarlo fácilmente en
múltiples aplicaciones que requieran esta funcionalidad; una sola clase Die puede
usarse para crear muchas Morir objetos. En este sección, nosotros voluntad mirar
en a " Morir " clase eso encapsula El código para generando a aleatorio entero
entre 1 y 6. Adentro el clase, allá es la implementación de un método. La firma de
este método (su visibilidad, su tipo de retorno, su nombre y su lista de parámetros)
es
público entero rollo()
De esto podemos ver que el método tiene visibilidad pública (puede ser
accedido por cualquier otro objeto), devuelve un “ int ” valor al código que llama
a este método, se llama “ roll ” , y no toma ningún parámetro como argumento
(los paréntesis están vacíos).
Dentro del método, la generación del número aleatorio y la aritmética son las
mismas que en nuestros ejemplos anteriores de simulación del lanzamiento de un
dado. Sin embargo, la última línea del método devuelve un valor al llamador del
método. En este ejemplo, el valor eso es devuelto es el entero que representa el
valor de el morir. Este es La clase completa:
paquete [Link].chapter6;
clase pública Die
{
público entero rollo()
{
doble Número aleatorio =
Matemá[Link](); número aleatorio
*= 6;
numeroaleatorio++;
devolver (int)Número aleatorio;
}
}
130 6 Creating Domain
Classes
Ahora podemos crear tantos objetos Die en el código del cliente como
queramos, sin necesidad de duplicar la implementación. En este ejemplo, se crean
dos objetos Die y se " lanzan "
paquete [Link].chapter6;
clase pública DiceRoller
{
público estático vacío principal(Cadena[] argumentos)
{
Morir morir1 = nuevo
Morir(); Morir
morir2 = nuevo
Morir();
int dadoTotal = [Link]() + [Link]();
[Link]("Total de 2 dados es :" + dadosTotal);
}
}
Una ventaja importante de encapsular código en objetos como este es que
podemos modificarlo. el implementación de un objeto métodos sin conmovedor
cualquier de el código que utiliza el objeto siempre que el comportamiento siga
siendo el mismo. Podríamos, por ejemplo, reemplazar el bastante torpe
implementación eso genera a aleatorio entero usando el Matemáticas clase por
usando el [Link] clase en cambio. Este clase tiene lo útil método “
siguienteInt ” cual genera a aleatorio entero bastante que un número de punto
flotante, como lo hace “ [Link] ” . Además, el método puede pasarse a
parámetro a especificar el superior límite de el rango de aleatorio números a se
generará. La siguiente implementación del “ getRoll ” de la clase Die El
método utiliza un objeto de el Aleatorio clase a más fácilmente generar a aleatorio
entero en el rango 1 – 6.
paquete [Link].chapter6;
importar [Link];
clase pública Die
{ pública entero
obtenerRoll()
{
Aleatorio generador de números aleatorios = nuevo Aleatorio();
entero Número aleatorio =
[Link](6) + 1; devuelve un
número aleatorio;
}
}
6.7 Clase Reutilización 131
Este tipo de cambio de código, donde mejoramos el diseño de un método sin
afectar su comportamiento, se conoce como refactorización y es una técnica útil
para garantizar que la calidad del código sea lo mejor posible.
6.8 Estático Campos y Métodos
De el ejemplos nosotros tener visto entonces lejos, él debería ser claro que
nosotros poder escribir a clase de la cual Se pueden utilizar muchos objetos
diferentes creado; hay una clase pero puede haber muchos objetos de eso clase.
Cuando a Java programa comienza correr, mucho Las clases requeridas para ese
programa se cargan en la memoria mediante el cargador de clases de Java, por lo
que pueden ser usado a crear dinámica objetos en tiempo de ejecución. Sin
embargo, en suma a ser La fuente para crear objetos, las clases existen por derecho
propio y también pueden tener campos. y métodos eso pertenecer a el clase,
bastante que el objetos. El ventaja de un clase de campos y métodos es eso ellos
poder ser accedido y usado incluso si No Se han creado objetos de esa clase. Un
contexto en el que esto resulta útil es al escribir métodos. eso hacer no necesidad
cualquier objeto estado en orden a trabajar. Con estos métodos, La respuesta
siempre sería la misma sin importar qué objeto (de ese tipo) se reciba. el mensaje.
En semejante casos, él es más apropiado para el clase a tener El método. Este tipo
de método es como una función tradicional en un lenguaje no orientado a objetos,
donde se proporcionan parámetros a la función y esta devuelve un valor, sin
necesidad de acceder a ningún campo de objeto.
Un ejemplo podría ser una clase ExchangeRate con métodos que proporcionen
información sobre diferentes conversiones de divisas. Dado que esta información
es global, y no dependiente en el estado de cualquier objetos, él quería residir en el
clase sí mismo. Un tipo de cambio clase podría ser capaz a decir a nosotros, para
ejemplo, el intercambio tasa Entre dos diferente Monedas sin cualquier individual
Tipo de cambio objetos Necesitando a ser creado.
Un ejemplo simple de un campo estático de nuestro ejemplo de Curso sería uno
que rastrea cuántos objetos de la clase Curso se han creado. Este campo está
mucho mejor ubicado en el clase que en individuo objetos. Primero porque lo es
Todavía es posible acceso el campo incluso si No objetos tener estado creado
todavía, y segundo porque El valor solo necesita mantenerse en un lugar, dentro
de la clase. Si fuera un campo de objeto, su valor debería actualizarse en cada
objeto de la clase, cada vez que se crea un nuevo objeto.
Los campos y métodos que pertenecen a la clase están marcados como “
estáticos ” . Aquí hay un campo estático que podría agregarse al “ Curso ”. clase,
para contar cuantos cursos tiene estado creado. Aparte de el palabra clave “
estático ” él es justo como declarando un campo objeto .
privado estático entero Número de cursos creados = 0;
132 6 Creating Domain
Classes
A hacer seguro este valor incrementado cuando a nuevo objeto es creado,
nosotros podría Agregue a este valor en el constructor:
numeroDeCursosCreados++;
Como largo como nosotros tener encadenado nuestro constructores juntos,
nosotros debería solo necesidad a Haz esto en un solo lugar.
6.8.1 Estático Métodos
Los campos estáticos suelen accederse mediante métodos estáticos (es decir, si el
campo pertenece a la clase, entonces también deberían hacerlo los métodos que
acceden a él). A continuación, se muestra un ejemplo de un método estático que
devuelve el valor del campo numberOfCoursesCreated:
público estático entero obtenerNumeroDeCursosCreados()
{
devolver numeroDeCursosCreados;
}
Nuevamente, esto es como declarar un método normal, excepto por la adición
de la palabra clave “ static ” . Aquí se muestra parte de la clase Course, que
incluye el campo y el método estáticos, y un constructor actualizado.
público clase Curso
{
privado estático entero Número de cursos creados =
0; nombre de cadena privada;
int privado numeroDeDías;
privado doble
precioPorPersona;
// constructor
público Curso(Cadena nombre, entero días, doble precio)
{
setName(nombre);
setNumberOfDays(días);
setPricePerPerson(precio);
numberOfCoursesCreated++;
}
público estático entero obtenerNumeroDeCursosCreados()
{
devolver numeroDeCursosCreados;
}
//…etc.
}
6.8 Estático Campos y Métodos 133
6.8.2 Invocando Estático Métodos
Los métodos estáticos (de clase) se deben invocar utilizando la clase, no un objeto.
Observe cómo aquí se utiliza el nombre de clase “ Course ” , no el nombre
de un objeto Course:
entero cursos = [Link]();
En realidad, los métodos estáticos también pueden ser invocados por un objeto,
ya que no causan un compilador. error a hacer este, pero él hace no ayuda el
legibilidad de el código entonces tú Si lo intentas, recibirás una advertencia de
Eclipse. Por otro lado, no puedes invocar métodos de objetos usando una clase.
6.8.3 Estático Final Campos
Lo más parecido a una constante en Java es un campo final estático. La palabra
clave “ final ” significa que el valor del campo no se puede cambiar una vez
que se ha asignado.
Por ejemplo, podríamos añadir un campo final estático a la clase para
almacenar el nombre de la empresa de formación. Como estos datos no deben
cambiar dinámicamente, se marcan como finales y, como no tiene sentido
repetirlos en todos los objetos, son estáticos; existen una vez en la clase. Como no
se pueden cambiar, se pueden hacer públicos, ya que no hay ningún cambio.
necesidad a encapsular él detrás adquiridor y setter métodos. El Nombramiento La
convención para valores constantes en Java es utilizar todas las letras mayúsculas,
utilizando guiones bajos como separadores, como en este ejemplo:
público estático final Cadena NOMBRE DE EMPRESA = "Mega impresionante
corporación";
6.8.4 Estático Métodos en Java Biblioteca Clases
Esto puede ser un Buen momento para reflexionar sobre el hecho de que el “
principal ” El método está marcado como “ estático ” . Por lo tanto, él es a
método eso pertenece a el clase eso contiene él. Nosotros También he visto que la
clase Math se utiliza para invocar métodos directamente, es decir:
Matemá[Link]();
Deberías poder ver en este código que " random " es un método estático; está
siendo invocado directamente en el clase bastante que en un objeto. Nosotros
nunca instanciar Un objeto de el Matemáticas clase porque en hecho todo es
métodos son estático (tú poder ver este Si miras el Javadoc de la clase). No
podrías crear un objeto de la clase Math incluso si quisieras, porque su constructor
está marcado como " privado " .
La clase String también tiene varios métodos estáticos, incluido “ valueOf ” .
Este método toma un tipo primitivo de Java como parámetro y lo devuelve como
una cadena, es decir,
Cadena
134
una cadena = [Link]( valor );
6 Creating Domain
Classes
134 6 Creating Domain
Classes
Para ejemplo, él poder convertir a doble a a Cadena:
doble Número real = 3.1417;
Cadena doble cadena = [Link](númeroreal);
Allá son muchos diferente versiones de “ valorDe ” porque él es sobrecargado
a funciona con todos los tipos de datos primitivos de Java y lo utiliza
[Link] cuando muestra tipos primitivos:
[Link](3.1417);
// el doble es implícitamente convertido a a Cadena
// usando [Link]
Mientras estamos en el tema de “ [Link] ” , tiene un ejemplo de un
campo estático público. “ out ” es en realidad un campo estático público de la
clase System (un objeto de la clase PrintStream), y “ println ” es un método de ese
objeto.
A partir de estos pocos ejemplos, se puede ver que los campos y métodos
estáticos se utilizan con frecuencia en Java.
Ejercicio 6.4
• Agregue un método estático a su clase Course que calcule el costo por persona
de un curso personalizado que se cobra a una tarifa fija , en lugar de por
persona.
• Aprobar el departamento tasa y el número de Participantes a el método y
devolver el costo por cabeza
• Agregar a constante a su Curso clase eso contiene el nombre de el
empresa de formación
• Mostrar el valor de el constante en su prueba código
• Actualizar su prueba clase a ejercicio su cambios
6.9 Objetos como Java Frijol Componentes
En esta sección final, analizaremos brevemente algunos de los aspectos más
simples de la escritura de objetos como componentes. El debate sobre las
diferencias entre objetos y componentes puede volverse muy complicado, pero la
definición más simple de un componente es que es un objeto que se puede “
conectar ” a una aplicación, como una herramienta de programación visual o un
generador de páginas web dinámico. Para que esto funcione, debe ser fácil para la
aplicación “ entender ” el componente. Una forma sencilla de hacerlo es seguir
algunos patrones de nombres estándar para nuestros métodos de objeto. Las reglas
para escribir objetos Java como componentes se describen en “ JavaBeans ”.
especificación. La especificación establece que “ Un Java Bean es un software
reutilizable componente eso poder ser manipulado visualmente en a constructor
herramienta " . A pesar de
6.9 Objects as Java Bean 135
Components
La especificación completa es bastante compleja, es útil seguir algunas de sus
reglas más básicas para hacer que nuestras clases sean más amigables con las
herramientas.
El objeto simple Die desde antes en este capítulo tiene un método que Se le dio
un nombre descriptivo como " roll " . Aunque este nombre de método es
expresivo para el programador, no lo es. no seguir una estándar Nombramiento
convención. Este quería dificultar que una herramienta de programación u otro
entorno de objetos realice suposiciones sobre qué el objetivo de este método
podría ser. Uno de el muchos aspectos de a JavaBean Es que admite propiedades
y es este aspecto el que exploraremos aquí. Las reglas relacionadas con las
propiedades son:
• JavaBeans tener propiedades eso son definido por métodos.
• A propiedad es legible si él tiene a pareo “ Obtener nombre de propiedad ” método.
• A propiedad es escribible si él tiene a pareo “ establecer nombre de propiedad ” método.
• Las propiedades booleanas legibles se pueden definir mediante un método que
comience con “ is ” , en lugar de (o además de) un método que comience con “
get ” .
• A propiedad es no necesariamente un atributo.
¿Qué queremos decir con que una propiedad tiene un método coincidente?
Estos se relacionan con una forma estándar de escribir nombres de métodos. El
nombre de una propiedad se toma como el nombre que sigue a “ get ” o “ set ” en
el nombre del método, donde la primera letra de la propiedad está en minúscula.
Por ejemplo, tomemos el ejemplo de la clase Course con sus getters y setters
generados. Estos siguen las reglas para las propiedades JavaBean. La clase course
tiene propiedades legibles y escribibles llamadas “ name ” , “ numberOfDays ” y
“ precioPorPersona ” . Un importante punto a hacer aquí es eso La propiedad
nombre es determinado enteramente por el método nombres, no por el actual
nombre de un campo interno. Si el campo de la clase se llamara “ courseName ”
en lugar de “ name ” él quería no hacer cualquier diferencia a el nombre de el
propiedad. Regresando Para la clase Die, el lanzamiento del dado no es una
propiedad de JavaBean (en términos de la especificación) porque el método no
comienza con “ get ” o “ set ” . Para girar el dado en a básico JavaBean nosotros
necesidad a cambiar el nombre de “ roll ” a “ obtenerRoll ” . Este debería deja en
claro que una propiedad no es un campo; la clase Die no tiene campos, pero “ roll
” es un campo legible propiedad (aunque no a escribible uno, desde allá es No “
establecerRoll ” método).
Nota
Debe tener en cuenta que algunos entornos JavaBean (por ejemplo, JavaServer
Pages) requieren que una clase bean tenga un constructor con cero argumentos,
aunque la especificación no lo exige. Además, aunque una propiedad booleana se
puede expresar con un " es ..." método, hay algunas herramientas en las que se
puede colocar un frijol que hacer no usar el “ es ” forma de legible propiedad
y siempre usar " conseguir " .
6.9.1 Reflexión
¿Cuál es entonces el propósito de seguir las reglas de JavaBeans como la
136 6 Creating Domain
Classes
denominación de propiedades? patrones eso nosotros tener miró ¿en? El razón
es eso él permite herramientas a
6.9 Objects as Java Bean 137
Components
“ introspección ” en JavaBean componentes y entender qué cierto métodos son
Para ello, utilizan diversas formas de “ reflexión ” , que es la capacidad de
obtener metadatos . (datos acerca de datos) de a Java clase. Java apoya reflexión
con el “ [Link] ” paquete. Veremos uno o dos aspectos muy simples de
la reflexión para demostrar cómo los patrones de nombres de JavaBean pueden
ayudar a los entornos de programación a obtener información sobre las clases.
Lo primero que podemos hacer es preguntar a un objeto sobre su clase. Esto se
logra utilizando el método “ getClass ” , que devuelve un objeto de tipo
[Link], por ejemplo
Clase CursoClase = [Link]();
Nota
Recibirá una advertencia del compilador en esta línea. Esto está relacionado con
el uso de genéricos, que abordaremos en el capítulo 12. Mientras tanto, puede
ignorar esta advertencia sin problemas.
Una vez que tenemos acceso al objeto Class, este tiene una serie de métodos
que nos informarán sobre la clase. Por ejemplo, podemos usar el método “
getName ” para que nos indique la información completa calificado nombre de el
clase, o “ obtenerNombreSimple ” a conseguir solo el nombre de clase, sin el
nombre del paquete:
Cadena nombreClaseCompleto = [Link]();
Cadena nombreClaseSimple = [Link]();
Nosotros poder conseguir un formación de todo el métodos eso son declarado
en el clase con
“ obtenerMétodosDeclarados ” , cual devoluciones un conjunto de Objetos
[Link] fl [Link] .
Método[] métodos = [Link]();
Al llamar a “ getName ” en todos los objetos de método, podemos averiguar
cómo se llaman todos los métodos:
para(int i = 0; i < mé[Link]; yo++)
{
[Link](métodos[i].getName());
}
Este ejemplo demuestra una reflexión simple sobre un objeto de la clase
Course (note la importancia necesaria del “ Método ” clase del paquete “
[Link] ” :
138 6 Creating Domain
Classes
paquete [Link].chapter6;
importar
[Link]; clase
pública CourseReflection
{
público estático vacío principal(Cadena[] argumentos)
{
Curso miCurso = nuevo Curso("Agile Métodos", 5, 20000.0);
Clase cursoClase = [Link]();
Método[] métodos = [Link]();
[Link]([Link]() + " métodos:");
para (int i = 0; i < mé[Link]; i++)
{
[Link](métodos[i].getName());
}
}
}
El producción de este programa es
[Link] métodos:
obtener
Nombre
estable
cerNomb
re
obtenerPrecioPorPersona
obtenerNumeroDeDías
establecerNumeroDeDías
establecerPrecioPorPersona
obtenerNumeroDeCursosCreado
s
El punto importante a tener en cuenta aquí es que una herramienta de software
puede usar este tipo de métodos para obtener información sobre su clase y si ha
seguido las convenciones de JavaBean. semejante como propiedad Nombramiento
patrones entonces el herramienta sabe acerca de el Propiedades de su objetos. De
el lista de método nombres arriba, él quería ser capaz a inferir que “
númeroDeDías ” , “ precioPorPersona ” y “ nombre ” son propiedades y sabría
cuales unos eran legible y cual eran Escribible. Uno muy útil solicitud La ventaja
de los JavaBeans con propiedades es que se pueden utilizar en JavaServer Pages
(JSP) para crear contenido dinámico en páginas web utilizando etiquetas XML
especiales.
Ejercicio 6.5
Escribe una “ Moneda ” Clase que encapsula el código para simular el
lanzamiento de una moneda. clase debería incluir a “ obtener cara ” método eso
devoluciones cualquiera “ cabezas ” o “ colas ” .
Ejercicio 6.6
El antiguo “ libro del cambio ” chino (el I Ching , pronunciado “ yee jing ” )
describe a método de divinidad usando 50 milenrama tallos. Para aquellos OMS
6.9 Objects as Java Bean 139
Components
hacer no Tenga a mano 50 tallos de milenrama, se pueden utilizar 3 monedas en su
lugar. Escriba una clase con un método principal eso simula el volteando de 3
Monedas y muestra el amable de hexagrama línea que representan. Esta será una
de las siguientes:
140 6 Creating Domain
Classes
Tres cabezas viejas Línea Yang ---- o --- -
Línea Yin antigua de tres colas ----
incógnita ---- Dos cabezas y una cola Línea Young
Yang ----------- Dos cruz y a cabeza
Joven Línea Yin ----
--- -
Sostener el Acuñar objetos en un formación.
Usar adecuado Unicode personajes a mostrar el correcto hexagrama línea como
así como el nombre.
Ejercicio 6.7
Un hexagrama completo del I Ching consta de seis líneas de hexagramas. Amplía
tu respuesta al ejercicio anterior para que muestre un hexagrama completo.
Encapsula tu código dentro de una clase “ Hexagrama ” . Esta clase debe incluir
un método para mostrar un hexagrama completo.
6.10 El “var” Palabra clave
La “ var ” La palabra clave se agregó en Java 10. No es lo mismo que el uso de “
var ” De manera vaga mecanografiado idiomas semejante como JavaScript o
Pitón, dónde el tipo de el datos o el objeto al que hace referencia una variable
puede cambiar con el tiempo. Java sigue siendo un lenguaje de tipado estático,
donde el tipo de una variable o referencia no se puede cambiar después de la
declaración. En Java, “ var ” poder solo ser usado para local variable tipo
inferencia, lo que significa eso nosotros poder declarar local variables dentro a
método sin especificando Su tipo. El compilador infiere el tipo real a partir de los
datos u objetos a los que hace referencia la variable. Por ejemplo, en lugar de crear
una variable local como esta:
Cadena Hola cadena = "Hola";
Nosotros podría escribir
variedad Hola cadena = "Hola";
“ var ” poder solo ser aplicado a local variables, no campos o método firmas. A
dar un muy simple, ejemplo de usando “ var ” en a método, nosotros podría
considerar el siguiente versión del método “ getRoll ” de la clase “ Die ” :
público entero obtenerRoll()
{
variedad generador de números aleatorios = nuevo Aleatorio();
variedad Número aleatorio =
[Link](6) + 1; devuelve un
número aleatorio;
}
En lugar de indicar “ Random ” e “ int ” como los tipos de datos de las dos
variables locales, ambas se declaran como “ var ” . El compilador puede inferir
que “ randomNumberGenerator ” es a Aleatorio objeto porque de el llamar a el
constructor.
6.10 El “ var ” Palabra clave 139
De manera similar, se puede inferir que “ randomNumber ” es un “ int ” porque
ese es el tipo de retorno de “ nextInt ”. método. Se puede realizar un cambio
similar en el método “ principal ”. método que utiliza un objeto “ Die ”
público estático vacío principal(Cadena[] argumentos)
{
variedad morir1 =
nuevo Morir(); var
morir2 = nuevo
Morir();
var dadoTotal = [Link]() + [Link]();
[Link]("Total de 2 dice es :" + dadosTotal);
}
Entonces, qué es el punto de “ var ” ? En esencia, él es a legibilidad mecanismo. En
algunos
casos, teniendo a referirse a el tipo de un objeto cuando creando él poder hacer
código bastante prolijo y complejo, y usando “ var ” poder hacer código más
legible. Él también hechos como una señal para que los programadores se
aseguren de nombrar sus variables claramente para que otros que lean el código no
pierdan ninguna información significativa.
Una pequeña cosa a tener en cuenta es que, aunque el título de esta sección se
refiere a “ var ” como palabra clave, él es más exactamente a " reservado tipo
nombre " . Este puede parecer como a Es una distinción sutil, pero significa que
cualquier código heredado que use “ var ” como nombre de una variable, método
o paquete no se verá afectado al actualizar a versiones de Java que admitan “ var ”
.
Ejercicio 6.8
Observa el código que has escrito en los ejercicios de este capítulo y comprueba si
hay variables locales cuyas declaraciones de tipo podrían sustituirse por “ var ” ,
por ejemplo, el código de hexagrama de los Ejercicios 6.6 y 6.7.
6.11 Resumen
Este capítulo se inicia con una discusión de conceptos orientados a objetos, como
la información. ocultación y el encapsulación de estado y comportamiento adentro
objetos. A continuación se presentó una ilustración de cómo se representan las
clases y sus campos y métodos. en el Unificado Modelado Idioma (UML) .
Posterior código Los ejemplos mostraron cómo se pueden crear nuevas clases de
dominio en Java, junto con sus campos y métodos. y constructores, y cómo
Eclipse proporciona automatizado apoyo para alguno De estos tareas. El
sobrecarga de el constructor método a proporcionar maneras de También se
explicó la creación de objetos con diferentes conjuntos de argumentos. La
discusión adicional sobre la encapsulación abarcó el encadenamiento de
constructores y los cuatro modificadores de visibilidad: “ público ” , “ privado ” ,
“ predeterminado ” y “ protegido ” . Al final del capítulo anterior, se presentó la
documentación del código Javadoc. En este capítulo, vimos que la herramienta
Javadoc se puede utilizar para generar documentación HTML para nuestras
propias clases, ya sea de dentro Eclipse o de el dominio línea. Nosotros también
sierra
142 alguno de el 6 Creating Domain
Classes
140 6 Creating Domain
Classes
Etiquetas Javadoc especiales que se pueden agregar a los bloques de comentarios
para proporcionar información adicional en el Javadoc generado. La parte final del
capítulo exploró aspectos más específicos de la creación de clases, incluidos los
campos y métodos estáticos, los componentes JavaBean, la reflexión y la palabra
clave “ var ” , que se puede usar con variables locales para permitir que el
compilador infiera sus tipos de datos.
Objetos que trabajan juntos:
asociación, agregación y 7
Composición
Muchos objetos poder ser visto como ser hecho arriba de menor objetos. Para
ejemplo, a Un reloj está formado por una serie de componentes que, en conjunto,
se combinan para formar el objeto completo. La combinación de objetos puede
existir en muchas capas, y un componente más grande (como el mecanismo)
puede estar formado a su vez por una colección de componentes más pequeños.
Figura 7.1 muestra una reloj mecánico como Una combinación de partes
componentes
Ambos agregación y composición son términos eso describir objetos eso son
Compuesto por otros objetos, pero podemos hacer algunas distinciones entre estos
términos. La composición es simplemente un tipo de relación de objetos donde el
El objeto en su conjunto y sus partes componentes tienen una relación muy
estrecha, de modo que todos los objetos son totalmente interdependientes, por
ejemplo, al tener una dependencia de duración de vida . Esto significa que la
duración de vida de las partes componentes está ligada a la duración de vida del
objeto en su conjunto. Por ejemplo, las partes componentes de un teléfono móvil
suelen desecharse o reciclarse cuando el propio teléfono llega al final de su vida
útil. Otra forma de pensar en la composición es que los componentes solo son
accesibles a través de la interfaz externa de la composición, no de forma
independiente, como por ejemplo utilizando el procesador de una computadora.
cuando el entero computadora es ser usado. El procesador quería no ser Se utiliza
de forma aislada. Cuando los componentes no tienen un papel independiente fuera
de una agrupación particular, podemos describirlo como una composición. En
términos del reloj, podríamos considerar el reloj y sus componentes mecánicos
como una composición, pero la relación entre el reloj y su batería como una
relación de agregación más flexible, ya que aunque la batería puede ser parte del
reloj, también podría existir en otro contexto. Podríamos hacer una comparación
similar utilizando el ejemplo de un teléfono móvil. Se pueden utilizar módulos de
identidad (SIM) o tarjetas de memoria en un teléfono, pero también se pueden
sacar y usar en otros dispositivos, por lo que se agregan en el teléfono, pero no son
parte de una composición. A veces, al diseñar relaciones de objetos, es útil
considerar esta distinción, ya que puede afectar la forma en que implementamos
nuestras clases.
© Saltador Naturaleza Suiza Estado 2020 D. Parsons,
Foundational Java , Textos en Ciencias de la Computación,
141
[Link]
142 6 Creating Domain
Classes
142 7 Objects Working
Together …
Higo. 7.1 Un objeto puede
Estar compuesto de objetos
componentes más pequeños
7.1 Agregaciones como Colecciones
Las relaciones de composición son muy estables. Por el contrario, a menudo
encontramos que algunos objetos agregados se agrupan en conjuntos mucho más
dinámicos y desestructurados. Los atascos de tráfico, las colas de autobús y los
mercadillos son ejemplos de situaciones en las que los objetos se agrupan de
forma más bien transitoria e informal. generalmente aparecer en alguno amable de
contexto; a camino, a autobús refugio, a sala de la iglesia, que actúan como
contenedores para las colecciones de objetos. Ejemplos más específicos de
contenedores podrían ser los carritos de la compra, los autobuses, las furgonetas,
etc. En el mundo que nos rodea, los objetos se encuentran con frecuencia en
contenedores, quizás en más de un nivel. Por ejemplo, los aperitivos pueden
colocarse en pequeños paquetes que luego se colocan en bolsas grandes que se
colocan en cartulina cajas que son entonces poner En un recipiente eso es entonces
poner en el bodega de un barco (Fig. 7.2 )
El Lenguaje unificado de modelado proporciona alguno diferente sintaxis para
agregación y composición entonces podemos representar uno o el otro en diseño
Diagramas. Cifra 7.3 muestra el símbolos Para la composición (a lleno diamante)
y agregación (un vacío diamante). En este diseño, nosotros implicar eso a vista es
un agregación de alguno formas, pero el formas ' Vidas no depender en el vista, y
ellos puede ser accedido por otro objetos directamente. En Por otro lado, una
forma es una composición de una serie de puntos que juntos definen las
ubicaciones relacionado a el forma ([Link] el esquinas de a polígono). Desde estos
agujas sólo tienen sentido en el contexto de una forma particular, su vida útil está
vinculada a la de la forma y sólo son accesibles a través del objeto de forma, no
directamente.
7.2 Message 143
Passing
Higo. 7.2 Contenedores tener otro objetos adentro a ellos, cual puede en doblar contener otro objetos
View * Shape * Point
Higo. 7.3 Agregación y composición símbolos en El UML
7.2 Mensaje Paso
En el mundo real, las personas y los objetos interactúan constantemente. Por
ejemplo, interactuamos con los relojes: les damos cuerda, programamos sus
alarmas, cambiamos sus baterías, reiniciamos sus horas e interactuamos con ellos
de muchas otras maneras. Partes de los relojes también interactúan, por ejemplo,
cuando se activa una alarma cuando el reloj alcanza una hora determinada. En el
diseño orientado a objetos, llamamos a las personas que interactúan con los
objetos “ actores ” y a las relaciones entre los objetos que interactúan “
asociaciones ” . Nosotros hablar acerca de objetos " pasando mensajes ” a cada
otro. Sin estos tipos de conexiones entre objetos, no sirven para ningún propósito
útil, como un reloj en el desván.
144 7 Objects Working
Together …
7.2.1 Objeto Asociación
La agregación y la composición son tipos específicos de asociación. Una
asociación es simplemente un mecanismo para que los objetos de diferentes clases
(o incluso de la misma clase) se comuniquen entre sí. Las asociaciones pueden ser
de uno a uno (un objeto de una clase se asocia con otro objeto de una clase), de
uno a muchos (un objeto se asocia con muchos otros objetos de una clase) o de
muchos a muchos (muchos Los objetos de una clase se asocian con muchos otros
objetos de una clase). Los objetos que funcionan solos no producen muy útil
sistemas. Un orientado a objetos programa consiste de muchos objetos
colaborando a producir el requerido sistema comportamiento, como nosotros
sierra con el ejemplo de el Curso y Impartición del curso clases en el último
capítulo, cuando objetos de Estas diferentes clases estaban vinculadas entre sí a
través de una asociación. En el ejemplo precedente capítulos nosotros creado
alguno clases y Probado a ellos individualmente, pero este es No basta con crear
una aplicación que comprenda varios objetos. En este capítulo, veremos cómo un
sistema puede estar formado por diferentes objetos que se asocian entre sí.
7.2.2 Asociación Dirección
Las asociaciones describen las relaciones entre objetos de diferentes clases (o
incluso entre diferentes objetos de la misma clase). Estas asociaciones pueden
implementarse en una sola dirección o en ambas direcciones. Un reloj podría, por
ejemplo, asociarse con un objeto de calendario. Los mensajes pueden pasar del
reloj al objeto de calendario. calendario cada 24 horas, a decir el calendario a
cambiar en medianoche. Otro Los mensajes podrían pasar en la dirección opuesta,
de modo que el calendario podría indicarle al reloj cuándo mover un hora
adelante o atrás cuando el relojes cambiar en a específico fecha (Fig. 7.4 ).
En el Lenguaje de programación unificada, un asociación eso es no estirado
con un punta de flecha es ficticio a ser bidireccional (implementada en ambas
direcciones). En la figura 7.3 , las asociaciones tienen puntas de flecha que
muestran la dirección de la asociación; estas son asociaciones unidireccionales.
(implementado en uno dirección solo). Cifra 7.5 muestra a clase diagrama de
12
11 1 [Link]()
10 2
9 3
8 4
[Link]()
7 5
6
Higo. 7.4 Mensajes podría aprobar en ambos instrucciones entre a calendario y a reloj
7.2 Message 145
Passing
Reloj Diario
Higo. 7.5 Reloj y Calendario tener a bidireccional, uno a uno asociación
una clase de Reloj y una clase de Diario que tienen una asociación bidireccional.
Donde no se utiliza ningún símbolo de cardinalidad (por ejemplo el “ * ” para
significar " muchos " ) La asociación se asume ser uno a uno; un objeto Reloj se
asocia con un objeto Diario.
7.2.3 Implementando Asociaciones
Hasta ahora hemos estado hablando de conceptos orientados a objetos desde una
perspectiva de diseño, pero allá llega a punto dónde nosotros debe comenzar
hablando específicamente acerca de Cómo los objetos en software trabajar.
Cuando nosotros implementar asociaciones en Java código, este significa que los
objetos de una clase tendrán campos que hagan referencia a otros objetos. Como
ejemplo simple, volveremos a la clase Course y sus asociaciones. Hasta ahora,
hemos sugerido eso a Curso puede asociado con muchos Impartición del
curso objetos. Un CourseDelivery puede asociarse con una única ubicación,
donde se lleva a cabo un CourseDelivery (Fig. 7.6 ). Tenga en cuenta que en este
caso asumimos que las asociaciones son en una sola dirección. Las asociaciones
unidireccionales son más fáciles de implementar y mantener que las asociaciones
bidireccionales, por lo que generalmente son preferibles desde una perspectiva de
codificación.
En términos de código, el Curso necesitaría tener un campo que haga referencia
a muchos objetos CourseDelivery. La mejor manera de hacer esto sería usar una
de las clases Collection que cubriremos más adelante en este libro, pero mientras
tanto con la sintaxis que ya saber, nosotros podría implementar este uno a muchos
asociación usando un matriz. Tenga en cuenta la convención de nombres; a un
campo que hace referencia a muchos objetos se le asigna un nombre plural, "
entregas " en este ejemplo:
público clase Curso
{
privado Impartición del curso[] entregas;
// poder ser creado en el constructor
…
Course * CourseDelivery Location
Higo. 7.6 Asociaciones Entre Curso, Impartición del curso y Clases de ubicación
146 7 Objects Working
Together …
Course
requisito previo
Higo. 7.7 Una asociación entre Diferentes objetos de el Curso clase
El Impartición del curso clase quería tener a campo referenciando a soltero
Objeto de ubicación (esta es una asociación uno a uno).
público clase Impartición del curso
{
privado Ubicación ubicación;
// poder ser creado en el constructor
Ocasionalmente necesitamos una asociación entre objetos de la misma clase.
Por ejemplo, un Curso puede tener otro Curso como requisito previo. En UML,
trazaríamos la asociación desde la clase Curso hacia sí misma (Fig. 7.7 ).
En términos de código, esto simplemente significa que la clase Curso tiene un
campo que hace referencia a otro Curso:
público clase Curso
{
privado Curso requisito previo;
7.3 Asociando Objetos: El Serpientes y Escaleras Juego
En el siguiente ejemplo veremos cómo varias asociaciones, incluidas las
composiciones, son implementado en a simulado juego de Serpientes y Escaleras.
Él muestra Qué variado objetos (juego tablero, serpientes, escaleras, dados, etc.) se
unen a producir un programa. Serpientes y Escaleras (similar a el Toboganes y
Escaleras juego en el [Link].) es un juego tradicional británico, derivado de un
juego indio mucho más antiguo, basado en un tablero de 100 cuadrícula, alguno de
cual son conectado por serpientes o escaleras (Fig. 7.8 ). Los jugadores comienzan
en la casilla 1, luego lanzan un dado para mover las fichas en zigzag a lo largo de
cada fila del tablero, moviéndose hacia arriba cuando llegan al final de una línea. Si
caen en el cabeza de a serpiente, entonces ellos debe mover abajo a es cola, y si
ellos tierra al pie de a escalera ellos poder mover a es cabeza. El primero jugador
a tierra exactamente en
cuadrado 100 es el ganador.
Nota
Estos normas puede ser obvio a tú pero usando este ejemplo con a multicultural
¡La clase me demostró que no es obvio para todos!
7.3 Associating Objects: The Snakes and 147
Ladders Game
100
serpiente
1
escalera
Higo. 7.8 A Serpientes y Escaleras junta
El mayoría importante aspecto de este ejemplo es eso él es el primero programa
nosotros Hemos visto que incluye varios tipos de objetos que nosotros mismos
definimos. En los ejemplos anteriores nosotros tener visto programas eso usado
varios Java clases (Cadena, Fecha) etc., u objetos de nuestras propias clases, pero
hasta ahora no hemos creado objetos de diferentes clases de nuestra propia
creación y habilitados para comunicarse entre ellos. En Serpientes y escaleras,
voluntad escribe seis nuevas clases y reutilizar la clase Die del capítulo anterior.
Un ejemplo como este da a nosotros el oportunidad a considerar alguno diseño
decisiones, en particular, decidir quién debe asumir las responsabilidades. Es
importante en un diseño orientado a objetos para poner las responsabilidades en la
“ mejor ” clase. Por supuesto, a veces el " mejor " diseño es justo a asunto de
opinión, allá son muchos diferente maneras para diseñar un sistema, pero una de
las principales pautas para el diseño orientado a objetos es evitar tener algunos
objetos que solo contengan datos y otros que hagan todo el flujo del proceso .
gestión. Él es mucho mejor si datos y procesos son repartido a través de Las clases
en el lugar donde mejor encajen. En el juego de serpientes y escaleras hay algunos
objetos que será necesario crear, a saber:
• Tablero de juego
• Pieza de jugador
• Tablero cuadrado
• Serpiente
• Escalera
• Morir
Y de curso, allá voluntad también necesidad a ser un objeto a representar el juego sí mismo.
148 7 Objects Working
Together …
Die
getRoll() : int
Higo. 7.9 El Morir clase como a Lenguaje unificado de modelado diagrama, especificando el devolver
tipo de el “ obtenerRoll ” método
Nota
Algunas de las decisiones de diseño tomadas en este ejemplo no son ideales,
porque aún no hemos cubierto suficiente sintaxis de Java para aprovechar al
máximo las opciones de codificación disponibles .
La principal decisión de diseño que debemos tomar es qué responsabilidades
deben tener estos objetos. El lugar obvio para comenzar es la clase Die, ya que
creamos esta clase en el capítulo anterior. La función de un Die es lanzarlo, una
responsabilidad que ya implementa a través del método “ getRoll ” (Fig. 7.9 ).
Este ejemplo de diagrama de clases también muestra el tipo de valor devuelto por
el método, en este caso un int.
¿Qué pasa con la pieza del jugador? Podríamos llevar un registro de qué pieza
está en qué casilla usando BoardSquare, o incluso el juego en sí, pero la pieza del
jugador necesita algo significativo comportamiento si él es a tener a útil role en el
solicitud, entonces nosotros dará La pieza del jugador responsabilidad de
conocimiento ¿Qué BoardSquare? él Ocupa actualmente. Figura 7.10 muestra la
asociación entre una PlayerPiece y un BoardSquare. La punta de flecha en la
asociación muestra la dirección de la asociación (es decir, una PlayerPiece tiene
una referencia a un objeto BoardSquare). Para poder tener alguna forma de
diferenciar PlayerPieces separados, tienen un campo de “ color ” (este tendrá
captadores y definidores, que no se muestran aquí ya que no son comportamientos
interesantes). También hay captadores y definidores para la “ currentPosition ”.
campo. Estos se han incluido en el diagrama para dejar claro que también hay un
método “ moveTo ” . Ambos “ moverA ” y “ establecerPosiciónActual ”
llevar a Tablero cuadrado como a
PlayerPiece BoardSquare
color : String Posición actual
currentPosition : int
moveTo(BoardSquare) movePlayerPiece
getCurrentPosition() (PlayerPiece piece)
setCurrentPosition
(BoardSquare)
Higo. 7.10 El Pieza de jugador clase asociada a su Tablero actual
7.3 Associating Objects: The Snakes and 149
Ladders Game
parámetro, entonces qué es el ¿diferencia? Este es justo uno forma de diseño el
solución, pero en esta implementación el “ setCurrentPosition ” El método es el
primer paso en el proceso de mover la PlayerPiece, y el método “ moveTo ” El
método es el siguiente paso opcional. Esto se debe a que mover una pieza de
jugador puede ser un proceso de dos etapas: el movimiento inicial al siguiente
cuadrado según el lanzamiento del dado y luego el posible movimiento hacia
arriba o hacia abajo por una serpiente.
Piezas de jugador saber cual Tablero cuadrado ellos son en, pero Tableros
cuadrados también Necesitamos saber dónde se encuentran en el tablero de juego
general. En nuestra implementación, utilizaremos una matriz para que
BoardSquare tenga una " posición actual ". campo que contiene un int, que
representa el índice de el formación eso el Tablero cuadrado ocupa. Él es también
capaz mover una pieza de jugador a su posición actual. El método “
movePlayerPiece ” toma una PlayerPiece como argumento de parámetro (Fig.
7.10 ). Esta no es una asociación a largo plazo, solo una relación transitoria
mientras se mueve la pieza.
¿Qué tal las clases de serpiente y escalera? Son bastante interesantes desde el
punto de vista del diseño. perspectiva porque ellos son muy similar. En hecho,
ellos podría ser modelado como una sola clase que vincula dos cuadrados; si
llevan al jugador " arriba " o " abajo " en el tablero realmente no hace ninguna
diferencia en la implementación. Sin embargo, desde la perspectiva de intentar
hacer que el código sea legible y comprensible, él puede ser mejor a palo con
dos separado clases, en el menos para ahora (Fig. 7.11 ).
El aspecto clave de los constructores de ambas clases es que los dos
BoardSquares que definen los extremos de la serpiente o escalera se pasan al
constructor, de modo que tan pronto como exista una serpiente o escalera, sepa
dónde encaja en el tablero. Al igual que BoardSquare, las clases Snake y Ladder
tienen un método “ movePlayerPiece ” . es porque, como previamente descrito, a
del jugador mover puede consistir de dos Pasos. Primero, ellos mover a el
próximo junta cuadrado basado en su tirar de el morir. Entonces ellos pueden
necesidad a ser emocionado de nuevo, si ellos tener aterrizado en el cabeza de a
serpiente o el pie de una escalera.
¿Qué hacemos con la relación entre Serpientes, Escaleras y Cuadrados del
Tablero? A Tablero cuadrado necesidades a saber si él contiene el cabeza de a
serpiente, o el pie de un escalera (aunque lo hace no necesidad a saber si Tiene el
cola de una serpiente o el cabeza
Higo. 7.11 El Serpiente
y clases de escalera Snake
Snake(BoardSquare, BoardSquare)
movePlayerPiece(PlayerPiece)
Ladder
Ladder(BoardSquare, BoardSquare)
movePlayerPiece(PlayerPiece)
150 7 Objects Working
Together …
Snake
BoardSquare 0..1 Snake(BoardSquare,
BoardSquare)
movePlayerPiece(PlayerPiece)
currentPosition : int
movePlayerPiece {or}
(PlayerPiece piece) Ladder
addLadder(Ladder)
addSnake(Snake) 0..1 Ladder(BoardSquare,
BoardSquare)
movePlayerPiece(PlayerPiece)
Higo. 7.12 El Tablero cuadrado clase y es opcional asociación con cualquiera a Serpiente o a Escalera
de una escalera porque éstas no hacen que la Pieza del Jugador se mueva de
nuevo). Por lo tanto, agregar métodos a el Tablero cuadrado clase a agregar
cualquiera a Serpiente o a Escalera (Fig. 7.12 ). Esta parte del diseño también
muestra parte de la “ multiplicidad ” de las asociaciones, que indican cuántos
objetos están involucrados en cada asociación. La multiplicidad “ 0.1 ” significa
que puede haber cero o un objeto en la asociación. La restricción “ {o} ” ,
indicada por una línea discontinua que cruza las dos asociaciones de cuadrado a
serpiente y cuadrado a escalera, medio eso nosotros no puedo tener una serpiente y
una escalera en cualquier casilla.
El siguiente componente que veremos es la clase GameBoard, que representa el
tablero de Serpientes y Escaleras en general, que comprende 100 BoardSquares
(Fig. 7.13 ). GameBoard siempre inicia el proceso de mover una PlayerPiece con
su propio método “ movePlayerPiece ” .
GameBoard BoardSquare
100
GameBoard() movePlayerPiece(PlayerPiece)
getStartSquare() addLadder(Ladder)
movePlayerPiece addSnake(Snake)
(PlayerPiece)
Higo. 7.13 El Tablero de juego clase, una composición de 100 cuadrados de tablero
7.3 Associating Objects: The Snakes and 151
Ladders Game
:GameBoard
1. moverA(Cuadrado del tablero)
:PlayerPiece
2. moverPiezaJugador(PiezaJugador)
:BoardSquare 4. setCurrentPosition(Cuadrado del tablero)
3. moverPiezaJugador(PiezaJugador)
:Ladder
Higo. 7.14 Lenguaje unificado de modelado colaboración diagrama demostración objeto
interacciones en el Serpientes y Juego de escaleras
Todos los diagramas que hemos utilizado hasta ahora representan relaciones de
clases estáticas. Sin embargo, la figura 7.14 es un diagrama de
colaboración/comunicación UML dinámico que indica una posible secuencia de
paso de mensajes entre objetos. En estos diagramas, que muestran objetos en lugar
de clases, un objeto se indica subrayando el clase nombre y anterior él con a colon.
Si el objeto tiene a nombre específico puede aparecer antes de los dos puntos, pero
esto se puede omitir. Esta figura ayuda a explicar cómo el varios mensajes aprobar
entre el objetos nosotros tener miró en entonces lejos cuando una Pieza de Jugador
se mueve y aterriza, en este ejemplo, en un Cuadrado del Tablero que contiene el
pie de una Escalera. Primero, el Tablero de Juego le dice a la Pieza de Jugador que
se mueva a un Cuadrado del Tablero. El Cuadrado del Tablero luego verifica si
tiene una serpiente o una escalera. Si es así (como en la Fig. 7.14 , donde tiene una
escalera) activa ese objeto para mover la Pieza de Jugador a su posición final para
este movimiento.
Finalmente, el Serpientes y escaleras clase hechos como el programa entrada
punto, y crea el GameBoard y las PlayerPieces (Fig. 7.15 ). Tiene un método “
main ” que crea una instancia de la clase y activa el método “ play ” . Este
maneja el bucle principal del juego que se repite hasta que el juego termina.
SnakesAndLadders
play()
Higo. 7.15 El Serpientes y escaleras clase
152 7 Objects Working
Together …
PlayerPiece
moveTo(BoardSquare)
getCurrentPosition()
setCurrentPosition(BoardSquare)
Serpientes y escaleras
GameBoard
jugar()
GameBoard()
getStartSquare()
Die movePlayerPiece(PlayerPiece)
getRoll()
Snake
Snake(BoardSquare,
BoardSquare) 100
movePlayerPiece
0. .1 BoardSquare
(PlayerPiece)
movePlayerPiece(PlayerPiece)
{or}
Ladder addLadder(Ladder)
addSnake(Snake)
Ladder(BoardSquare, 1. .0
BoardSquare)
movePlayerPiece
(PlayerPiece)
Higo. 7.16 Diagrama de clases UML que muestra las clases, métodos y asociaciones en el
programa de serpientes y escaleras
Figura 7.16 muestra el conjunto completo de clases en el juego de serpientes y
escaleras con sus asociaciones y métodos públicos.
7.3.1 El Serpientes y Escaleras Juego Fuente Código
En esta sección, repasaremos el código fuente de las distintas clases de Snakes. y
Escaleras juego. Sin embargo, nosotros voluntad comenzar con a breve
explicación de por qué la mayoría de estas clases y métodos no están marcados
como de visibilidad “ pública ” .
7.3 Associating Objects: The Snakes and 153
Ladders Game
[Link] Paquete Visibilidad
Clases eso son no declarado público tener " paquete " visibilidad, entonces no
puedo ser accedido desde afuera su paquete. Este es adecuado dónde estos clases
hacer no tener cualquier rol más allá del contexto de programación específico en el
que se están utilizando. Considere la diferencia entre las clases Die y Snake. Un
Die se puede utilizar en cualquier número de programas de juego, por lo que fue
útil hacer pública la clase para que otros clases podría fácilmente reutilizar él al
otro lado de otro paquetes. En contraste, el Serpiente La clase es totalmente atado
a el juego de Serpientes y Escaleras. Él tiene No realista oportunidad de reutilizar
fuera de este programa específico, por lo que no es necesario convertirlo en una
clase pública. De hecho, ninguna de el clases eso son parte de el serpientes y
escaleras juego son reutilizable en otros contextos, por lo que no es necesario que
ninguno sea público. La única clase pública es SnakesAndLadders para que se
pueda acceder a ella y jugar desde otros lugares. Si una clase tiene visibilidad de
paquete, entonces tiene sentido que sus métodos y constructores también tengan
visibilidad de paquete, a menos que tengan visibilidad " privada " .
Nota
Si está trabajando fuera de un IDE como Eclipse, puede colocar varias clases no
públicas en el mismo fuente archivo, aunque allá poder ser solo uno público
clase. El El nombre del archivo coincidiría con el nombre de la clase pública.
[Link] El Serpiente y Escalera Clases
Los objetos Snake y Ladder deben ubicarse en el tablero, de modo que puedan ser
referenciados por los BoardSquares en los que están ubicados y hagan referencia
al otro BoardSquares al que apuntan. Para establecer la posición de una serpiente,
hay un constructor parametrizado que toma las posiciones de la cabeza y la cola
como argumentos:
Serpiente(TableroCuadrado cabeza, Tablero cuadrado
cola) { setTail(cola);
[Link](esto);
}
El referencia a el cola de el serpiente es almacenado como a campo, porque el serpiente
necesidades
a ser capaz a mover a jugador pedazo a el cuadrado él termina en. Sin embargo,
allá es No Necesitamos almacenar una referencia a la cabecera, ya que esta se
guarda en BoardSquare (esta es una asociación bidireccional). Establecemos esta
referencia llamando a “ addSnake ” de BoardSquare. método, pasando “ esto
” serpiente como a parámetro. Este es un común forma de pasar referencias entre
objetos. Similarmente, el Escalera constructor víveres el parte superior de la
escalera y pasa de nuevo al BoardSquare que contiene su pie:
154 7 Objects Working
Together …
Escalera (Tablero Cuadrado) arriba, Tablero cuadrado
pie) { setTop(arriba);
[Link](este);
}
En ambos casos nosotros omitir el " público " prefijo porque el clase sí mismo
es no público, De todas formas, el constructor no podría ser llamado desde fuera
de su paquete.
Aparte de sus constructores, los únicos otros métodos de Snake y Ladder son
privados. adquiridor y setter métodos a administrar el posiciones de el
cabeza/parte superior o cola/pie. La pauta de código Esa impresión a el consola
son solo allí en Este ejemplo entonces eso Podemos ver qué sucede cuando se
ejecuta , algo que no haríamos normalmente en un código de producción. Esta es
la clase Snake completa.
paquete [Link].chapter7;
clase Snake
{
privado Tablero cuadrado cola;
Serpiente(TableroCuadrado cabeza, Tablero cuadrado cola)
{
setTail(cola);
[Link](esto);
}
privado vacío setTail(Cuadrado del tablero cola)
{
[Link] = cola;
}
privado Tablero cuadrado obtenerTail()
{
devolver cola;
}
vacío moverPiezaJugador(PiezaJugador encimera)
{
[Link]("Abajo el serpiente a " +
obtenerTail().obtenerPosición());
[Link](getTail());
}
}
El Escalera clase es muy similar
7.3 Associating Objects: The Snakes and 155
Ladders Game
paquete [Link].capitulo7;
clase Escalera
{
privado Tablero cuadrado arriba;
Escalera (Tablero Cuadrado) arriba, Tablero cuadrado pie)
{
setTop(arriba);
[Link](este);
}
privado vacío setTop(Cuadrado del tablero arriba)
{
[Link] = arriba;
}
privado Tablero cuadrado obtenerTop()
{
devolver arriba;
}
vacío moverPiezaJugador(PiezaJugador encimera)
{
[Link]("Arriba el escalera a " +
getTop().getPosition());
[Link](getTop());
}
}
[Link] El Tablero cuadrado Clase
El Tablero cuadrado clase Podría parecer bastante extraño con este diseño
acercarse. Esto se debe a que es una clase que necesita representar tres tipos
diferentes de cuadrados:
1. A cuadrado con a serpiente cabeza
2. A cuadrado con a escalera pie
3. A cuadrado con No serpientes o escaleras.
Entonces eso él poder cumplir todo tres roles, cada Tablero cuadrado objeto
contiene referencias tanto a una serpiente como a una escalera para que cualquiera
de ellas pueda colocarse en un cuadrado en particular. También hay métodos para
agregar serpientes o escaleras y métodos privados para verificar si hay una
serpiente o una escalera. La clase también realiza un seguimiento de la posición
del BoardSquare en la matriz que representa el GameBoard general. La principal
responsabilidad de un objeto de esta clase es mover una PlayerPiece a " este "
BoardSquare y posiblemente moverla nuevamente a lo largo de una serpiente o
una escalera.
156 7 Objects Working
Together …
clase Tablero cuadrado
{
// nosotros puede usar uno o ni de estos referencias
// para un cuadrado particular
private Snake aSnake = null;
private Escalera una escalera
= nulo; int privado posición;
TableroCuadrado(int posición)
{ setPosition(posición);
}
entero Obtener
posición () {
posición de
retorno;
}
privado vacío establecerPosición(int posición) {
[Link] = posición;
}
// nosotros puede desear a agregar
a serpiente cabeza void
addSnake(Serpiente s) {
una serpiente = s;
}
// o agregar el pie de una
escalera pública vacío
addLadder(Escalera yo) {
una escalera = yo;
}
// métodos a encontrar afuera si el cuadrado tiene a
serpiente o a escalera booleana privada hasSnake() {
devolver nulo != una serpiente;
}
privado booleano
tieneEscalera() { devuelve
nulo != aEscalera;
}
público vacío moverPiezaJugador(PiezaJugador encimera)
{ [Link](este);
si (tiene serpiente()) {
7.3 Associating Objects: The Snakes and 157
Ladders Game
[Link](contador);
}
si (tieneEscalera()) {
[Link](contado
r);
}
}
}
Notarás que aquí no hay ninguna comprobación de errores para garantizar que
un cuadrado determinado no no tener ambos Una serpiente y un escalera. Este
Puede ser dirigido mediante diferentes enfoques de diseño que abordaremos en el
próximo capítulo.
[Link] El Tablero de juego Clase
El junta tiene dos importante Responsabilidades:
1. Para configurar los cuadrados que forman el tablero, se crean y se añaden
serpientes y escaleras según corresponda. Esto se hace de acuerdo con el
diseño del tablero que se muestra en la Tabla 7.1 .
2. A comenzar cada mover de a Pieza de jugador por “ rodando ” el morir y
vocación el
“ moverA ” método
A veces a método espera a ser aprobado un objeto como a parámetro. Dónde
¿De dónde viene este objeto? En muchos casos, el objeto ya tendrá una referencia
en otra parte de un programa, por lo que su referencia puede simplemente pasarse
al método. En otros casos, el objeto no necesariamente necesitará existir en otro
lugar antes de que sea necesario. por el método. La forma en que las serpientes y
Escaleras son creado aquí es a llama a “ new ” sin una referencia de objeto
separada, y la implementación del constructor pasa “ this ” serpiente o escalera a
uno de los BoardSquares pasados como parámetro del constructor. En este
ejemplo, el BoardSquare “ squares[1] ” tendrá una referencia a la Escalera, y la
Escalera tendrá una referencia a BoardSquare “ squares[38] ” :
nuevo Escalera(cuadrados[38], cuadrados[1]);
Este es el completo Tablero de juego clase. Nota cómo él comienza por
importador el La clase de otro paquete:
Mesa 7.1 Las posiciones de las serpientes y escaleras en el
tablero Escaleras
From: 1 4 9 21 28 36 51 71 80
To: 38 14 31 42 84 44 67 91 100
Serpientes
De: 16 47 49 56 62 64 87 93 95 98
A: 6 26 11 53 19 60 24 73 75 78
158 7 Objects Working
Together …
paquete [Link].chapter7;
importar
[Link];
clase Tablero de juego
{
privado Tablero cuadrado[]
cuadrados; privado Die die;
// el formación voluntad ser uno cuadrado más grande que necesario
entonces eso nosotros
// poder comenzar de formación elemento 1, postergación
elemento 0 estático final int MAX_CUADRADOS = 100;
estático final entero CUADRADO DE INICIO = 1;
// el constructor crea el cuadrícula y añade el
// serpientes y Tablero de juego
de escaleras ()
{
morir = nuevo Morir();
cuadrícula = nuevo Tablero cuadrado[START_SQUARE +
MAX_CUADRADOS]; para (int i = CUADRADO_INICIAL; i <=
MAX_CUADRADOS; i++)
{
// agregar el próximo Cuadrado objeto a el
cuadrados del tablero[i] = new
BoardSquare(i);
}
// agregar el escaleras
nueva Escalera(cuadrados[38],
cuadrados[1]); nueva
Escalera(cuadrados[14],
cuadrados[4]); nueva
Escalera(cuadrados[31],
cuadrados[9]); nueva
Escalera(cuadrados[42],
cuadrados[21]); nuevo
Escalera(cuadrados[84],
cuadrados[28]); nuevo
Escalera(cuadrados[44],
cuadrados[36]); nuevo
Escalera(cuadrados[67],
cuadrados[51]); nuevo
Escalera(cuadrados[91],
cuadrados[71]); nuevo
Escalera(cuadrados[100],
cuadrados[80]);
// agregar el serpientes
nuevo Serpiente(cuadrados[16],
cuadrados[6]); nuevo
Serpiente(cuadrados[47],
cuadrados[26]); nuevo
Serpiente(cuadrados[49],
cuadrados[11]); nuevo
Serpiente(cuadrados[56],
7.3 Associating Objects: The Snakes and 159
Ladders Game
cuadrados[53]); nuevo
Serpiente(cuadrados[62],
cuadrados[19]); nuevo
Serpiente(cuadrados[64],
cuadrados[60]); nuevo
Serpiente(cuadrados[87],
cuadrados[24]); nuevo
Serpiente(cuadrados[93],
cuadrados[73]); nuevo
Serpiente(cuadrados[95],
cuadrados[75]); nuevo
Serpiente(cuadrados[98],
cuadrados[78]);
160 7 Objects Working
Together …
}
Tablero cuadrado obtenerStartSquare()
{
devolver cuadrados[START_SQUARE];
}
// este método ajusta el encimera posición
nula moverPiezaJugador(PiezaJugador
encimera)
{
Tablero cuadrado actual =
[Link](); int siguientePosición
= [Link]() + [Link]();
si(posiciónSiguiente > MAX_CUADRADOS)
{
[Link](
"Lo siento tú necesidad a tierra exactamente en el último cuadrado
a ¡ganar!");
}
demás
{
[Link](cuadrados[posiciónSiguiente]);
}
[Link]([Link]() + " encimera en " +
[Link]().getPosition());
}
}
[Link] El Serpientes y Escaleras Clase
Esta clase simula el juego y en este ejemplo se limita a crear una única
PlayerPiece y moverla dentro de un bucle “ while ” hasta que llegue al cuadrado
100. Esta clase y sus métodos son públicos, por lo que los objetos de esta clase se
pueden crear y usar desde el código en otros paquetes.
público clase Serpientes y escaleras
{
// referencia a el Tablero
GameBoard privado GameBoard;
// el constructor crea el Tablero
público SnakesAndLadders()
{
junta = nuevo Tablero de juego();
}
// este método hechos como a controlador para jugando el
juego público void play()
{
Contador PlayerPiece = new PlayerPiece("Rojo");
[Link]([Link]());
// iterar hasta que lleguemos a la fin (cuadrado 100)
mientras([Link]().getPosition()
7.3 Associating Objects: The Snakes and 161
Ladders Game
< Tablero de juego.MAX_CUADRADOS)
{
[Link](contador);
}
[Link]([Link]() +
" contador finalizado el " +
[Link]().getPosition());
}
// 'principal' crea a 'Serpientes y escaleras' objeto y
// comienza el juego
público estático vacío principal(Cadena[] argumentos)
{
Serpientes y escaleras mi juego = nuevo
SerpientesYEscaleras(); [Link]();
}
}
De curso, cada tiempo nosotros jugar el juego el producción voluntad ser
diferente. Aquí es Un ejemplo:
Arriba el escalera
a 14 Contador rojo
en 14 Contador rojo
en 15 Abajo el
serpiente a 6
Contador rojo en 6
Contador rojo en 11
Contador rojo en 17
Contador rojo en 20
Contador rojo en 24
Contador rojo en 30
Arriba el escalera
a 44 Contador rojo
en 44
Abajo el serpiente a
26 Contador rojo
sobre 26 Contador
rojo sobre 30
Contador rojo sobre
32 Contador rojo
sobre 37 Contador
rojo sobre 39
Contador rojo sobre
44 Contador rojo
sobre 48
Arriba el escalera
a 67 Contador rojo
en 67 Arriba el
escalera a 91
Contador rojo sobre
91 Contador rojo
sobre 94 Contador
rojo sobre 97
Lo siento tú necesidad a tierra exactamente en el último
cuadrado a ¡Gana! Contador rojo en 97
Rojo encimera en 100
Rojo encimera finalizado en 100
162 7 Objects Working
Together …
7.3.2 Cuando a Crear Objetos
Antes de dejar este ejemplo, vamos a reflexionar brevemente sobre la
diferencia entre crear objetos dónde ellos son declarado como campos y creando a
ellos en a constructor. Tome esta parte de la clase SnakesAndLadders, donde la
referencia a GameBoard se declara como un campo, pero el objeto en sí se crea en
el constructor.
// referencia a el Tablero
GameBoard privado GameBoard;
// el constructor crea el Tablero
público SnakesAndLadders()
{
junta = nuevo Tablero de juego();
}
Nosotros podría tener creado el objeto dónde él era declarado como a campo, para
ejemplo
// referencia a el Tablero de juego
privado Tablero de juego junta = nuevo Tablero de juego();
Dado que ambas opciones son posibles, ¿por qué podríamos optar por declarar
solo referencias? como campos y crear el objetos en el ¿constructor? Allá son dos
Razones comunes por las que podríamos hacer esto:
1. Cuando la relación entre objetos no es una composición fija sino una
asociación que puede cambiar con el tiempo, en este caso la referencia no
siempre tiene que apuntar al mismo objeto (o a cualquier objeto). Separar la
referencia de la creación del objeto nos da más flexibilidad .
2. Cuando objetos ser creado tener parametrizado constructores, y el Los
argumentos de los parámetros se pasan del constructor de un objeto al
constructor. de otro. Nosotros podría, para ejemplo, cambiar el junta clase
entonces eso Podría tener diferente números de cuadrícula para diferente
juegos, y aprobar este valor al tablero a través del constructor del juego.
Sin embargo, en algunas relaciones de composición puede tener sentido crear el
objeto cuando se declara, en lugar de hacerlo en el constructor.
Ejercicio 7.1
Añade otra pieza de jugador al juego de serpientes y escaleras e indica qué ficha
llega primero a la meta.
7.4 Asociación, Agregación o ¿Composición?
En el juego de serpientes y escaleras, existen varias asociaciones entre clases y
una agregación entre Tablero y Cuadrado. Esto significa que el objeto Tablero está
hecho arriba de muchos Tablero cuadrado objetos. Dado eso el junta y es
cuadrícula son
7.3 Associating Objects: The Snakes and 163
Ladders Game
Course Módulo
addModule(Module) 0..20 obtenerEvaluació
getModules() n()
getTotalCredits() obtenerPuntosCr
édito()
Higo. 7.17 Curso es una agregación del módulo objetos
estrechamente relacionado, nosotros podría de modo realista respecto este
como a composición Relación. ¿Cómo, entonces, podemos establecer una
distinción entre ambos? Aunque las líneas entre asociación, agregación y
composición a veces pueden ser borrosas, podemos decir en general que la
característica más importante es la propiedad. En una asociación, los objetos no se
poseen entre sí, sólo se comunican. En la agregación, un objeto puede poseer otros
objetos, pero también pueden tener una vida útil independiente y otras
características. asociaciones. En composición, el entero posee es regiones, y su
Vidas Probablemente sean idénticas. Es poco probable que las partes tengan
alguna relación con otros objetos fuera de la composición.
Los dos ejemplos restantes de este capítulo pueden ayudar a demostrar algunas
de las diferencias entre agregación y composición. Primero, observamos la
relación entre a curso de estudios y el módulos (sujeto áreas) eso él contiene. Por
ejemplo, un curso de formación en Java puede contener módulos sobre orientación
a objetos, manejo de excepciones e interfaces gráficas de usuario, entre muchos
otros. Aunque un curso es hecho arriba de módulos, estos módulos puede también
aparecer en otro cursos y el módulos en a curso puede ser reemplazado por otros.
Por lo tanto, nosotros poder respecto este como una relación de agregación (ver
Figura 7.17 ). El segundo ejemplo imita los componentes de hardware de una
computadora que están compuestos por otras piezas de hardware, donde el más
grande componente depende enteramente en es regiones y ellos tener No separado
existencia. Este es un ejemplo de composición (ver el diagrama UML en la Fig.
7.22 ).
7.4.1 Agregación Ejemplo
Las clases en este ejemplo son la clase Curso, que hemos presentado
anteriormente, y la clase Módulo. Un Módulo representa una materia que se
enseña como parte de a Más grande curso, entonces eso a curso en Java, para
ejemplo, podría tener muchos módulos relacionados con diferentes aspectos del
lenguaje. Un módulo tiene tres atributos:
1. El nombre de el módulo
2. A crédito punto clasificación para Certificación ([Link] 20 crédito agujas para a
lleno módulo o 10 puntos de crédito por medio módulo)
3. Un evaluación método ([Link] “ práctica ” , " prueba " , etc.).
7.4 Association, Aggregation or 163
Composition?
La clase Módulo de este ejemplo consta únicamente de campos y sus métodos
de obtención y establecimiento. Sería de esperar que surgieran comportamientos
más interesantes en un sistema más desarrollado.
paquete [Link].chapter7;
clase pública Módulo
{
cadena privada nombre;
privada entero puntos de
crédito; privado Cadena
evaluación;
público Módulo(Cadena nombre, entero agujas, Cadena
evaluar){ setName(nombre);
setCreditPoints(puntos);
setAssessment(evaluar);
}
público vacío setName(Cadena nombre)
{ [Link] = nombre;
}
público vacío establecerPuntosDeCrédito(int puntosdecredito)
{ [Link] = puntosdecredito;
}
público vacío setAssessment(Cadena evaluación){
[Link] = evaluación;
}
público Cadena getName(){
devolver nombre;
}
público entero
getCreditPoints(){ devolver
puntosdecredito;
}
público Cadena getAssessment()
{ devolver evaluación;
}
}
Curso objetos son agregaciones de cero o más Módulos. El Lenguaje unificado
de modelado diagrama En la figura 7.17 muestra cómo el dos clases relatar. El
máximo número de módulos en Se supone que un curso tiene 20.
El adicional elementos de el Curso clase para este ejemplo son un formación de
arriba hasta 20 Módulos, y a público método a devolver este formación. Allá es
también un atributo con métodos asociados para realizar un seguimiento del
número de módulos, lo cual es importante para ayudar a nosotros agregar módulos
sin yendo más allá de el límites de el formación. A demostrar
164 7 Objects Working
Together …
Un aspecto un poco más interesante de la relación Curso/Módulo es un “
getTotalCredits ” método eso añade arriba el créditos para todo el módulos en el
Curso. A continuación se muestran las partes de la clase Curso que son nuevas en
este ejemplo (se ha omitido el código conocido de ejemplos anteriores).
público clase Curso
{
// un formación de módulos
privado Módulo[] módulos = nuevo
Módulo[20]; int privado moduleCount = 0;
//alguno previamente introducido código omitido aquí…
// 'Añadir módulo' añade a parámetro módulo a el
[Link] void addModule(Módulo nuevo_módulo)
{
si(conteoDeMódulos < mó[Link])
{
módulos[moduleCount] = nuevo_módulo;
móduloCount++;
}
demás
{
[Link]("No se puede agregar más módulos");
}
}
público entero obtenerCréditosTotales()
{
entero total = 0;
para (en el interior i = 0; i <
obtenerConteoDeMódulos(); yo++) { total +=
obtenerMódulos()
[i].obtenerPuntosDeCrédito();
}
devolver total;
}
público Módulo[]
obtenerMódulos() { devolver
módulos;
}
público entero
obtenerConteoDeMódulos() {
devolver móduloCount;
}
Teniendo ensamblado nuestro agregación, nosotros poder hacer objetos de el
Curso clase, Agregar módulo objetos a a ellos y ver el resultado. El prueba clase
(ModuleRunner) hace No podemos hacer mucho aquí, pero podríamos seguir
desarrollando este sistema para que una colección de cursos y módulos
relacionados se puedan colocar en un catálogo o programar en ubicaciones,
proporcionando varios niveles de agregación.
7.4 Association, Aggregation or 165
Composition?
público clase Módulo Runner
{
público estático vacío principal(Cadena[] argumentos) {
Curso miCurso = nuevo Curso("Software pruebas", 5, 2000);
Módulo módulo1 = nuevo Módulo
("Unidad pruebas", 10, "Práctica");
Módulo módulo2 = nuevo Módulo
("Aceptación pruebas", 20, "Trabajo de curso");
Módulo módulo 3 = nuevo Módulo("Límite Valores", 10, "ninguno");
// agregar el módulos a el
curso
[Link](módulo1);
[Link](módulo2);
[Link](módulo3);
// mostrar los detalles del curso
[Link]([Link]()
+ " contiene el siguiente módulos:");
[Link]
("Módulo nombre \t crédito agujas \t
evaluación"); para (en el interior i = 0; i <
[Link](); yo++) {
[Link]([Link]()[i].getName() +
'\t' + [Link]()[i].getCreditPoints() + '\
t' + [Link]()[i].getAssessment());
}
[Link]("Total créditos = " +
[Link]());
}
}
El producción de correr este clase es
Las pruebas de software contienen los siguientes
módulos: Nombre del módulo Puntos de
crédito Evaluación
Pruebas unitarias 10 Prácticas
Aceptación pruebas 20 Trabajos de curso
Valores límite 10
ninguno Total de
créditos = 40
Ejercicio 7.2
Cree una clase Prospectus que sea una agregación de muchos cursos. Debe
permitir que se agreguen y visualicen cursos. Escriba una clase de prueba que cree
un objeto Prospectus y pruebe sus métodos.
7.5 Composición
El próximo ejemplo muestra cómo objeto composición poder ser usado a crear
objetos de componentes que están estrechamente unidos entre sí. Los objetos del
mundo real suelen ser claros ejemplos de composición, porque muchos objetos
están compuestos de objetos más pequeños. Los dispositivos electrónicos son muy
de este tipo y proporcionan el contexto para este ejemplo.
166 7 Objects Working
Together …
7.5.1 Lógica Puertas
A lógica puerta es a fundamental componente de digital electrónica, y el
comportamiento Algunos tipos de puertas lógicas serán muy familiares para
cualquiera que haya utilizado un programador. idioma. En Cap. 3 nosotros miró en
cómo Booleano operadores poder ser usado como parte de las condiciones
utilizadas con las selecciones ( “ si ” declaraciones) e iteraciones ( declaraciones
“ while ” o “ do … while ” ). Estos operadores booleanos se muestran en la
Tabla 7.2 .
En electrónica, estos operadores booleanos se implementan mediante
componentes conocidos como lógica puertas, cual comparar binario dígitos
bastante que condiciones. Para ejemplo, un AND puerta tiene dos o más entradas,
cada de cual puede tener el valor cero o uno. Tiene a soltero producción eso
voluntad tener el valor uno si, y solo si, todo el Entradas son También uno, de lo
contrario la salida será cero (Fig. 7.18 ). Para simplificar las cosas, nuestros
ejemplos supondrán que las puertas AND y las puertas OR tienen solo dos
entradas.
Una compuerta OR tendrá nuevamente dos o más entradas y una única salida,
pero en este caso la salida será un 1 si alguna de las entradas tiene el valor 1. Si
todas las entradas son cero, la salida será cero (Fig. 7.19 ).
A NO puerta tiene a soltero aporte y a soltero producción. Todo él hace es
convertir un entrada de cero a un producción de uno, o un aporte de uno a un
producción de cero (Higo. 7.20 )
Tabla 7.2 Operadores Operator Meaning Evaluates
booleanos y su significados
&& AND Are both conditions true?
|| OR Is either of the conditions true?
! NOT Is the condition false?
0 0 0 0 1 0 1 1
0 1 0 1
Higo. 7.18 Lo posible Entradas y salidas para Y puertas
0 0 1 1
0 0 1 1 0 1 1 1
Higo. 7.19 Lo posible Entradas y salidas para O puertas
7.5 167
Composition
0 1 1 0
Higo. 7.20 El posible Entradas y salidas para NO puertas
Para modelar estos tres tipos de puertas lógicas, crearemos tres clases. Son muy
simples y, de hecho, en esta implementación no tienen atributos y constan de un
solo método. Quizás te preguntes por qué estos métodos no están marcados como
estáticos, ya que los objetos no tienen estado. De hecho, para estos ejemplos esto
funcionaría bien, pero más adelante usaremos estas clases para representar objetos
componentes individuales, por lo que no usaremos un método estático. Estas son
las tres clases, comenzando con la clase AndGate. Observe cómo el “ return ” La
declaración se está utilizando en ambos lados de la condicional declaración.
Recordar eso a devolver declaración termina ejecución del método.
público clase AndGate
{
público entero obtenerSalida(int entrada1, entero entrada2)
{
si(entrada1 == 1 && entrada2 == 1)
{
devolver 1;
}
demás
{
devolver 0;
}
}
}
Este es el definición de el Puerta de Or clase
168 7 Objects Working
Together …
público clase Puerta de Or
{
público entero obtenerSalida(int entrada1, entero entrada2)
{
si(entrada1 == 1 || entrada2 == 1)
{
devolver 1;
}
demás
{
devolver 0;
}
}
}
Finalmente, el definición de el NoGate.
público clase NoGate
{
público entero obtenerSalida(int entrada1)
{
si(entrada1 == 1)
{
devolver 0;
}
demás
{
devolver 1;
}
}
}
Este prueba clase muestra cómo el puertas responder a diferente combinaciones
de aporte mostrando su salida en una simple “ tabla de verdad ” Formato. Las
tablas de verdad se utilizan a menudo para espectáculo el resultado de Booleano
lógica, y para números solo el orden de el valores No es importante. Para el
puertas con dos Entradas (Y puertas y O puertas) a Se puede utilizar una
cuadrícula bidimensional para mostrar la salida de cada par de valores, mostrando
el físico como Bueno como el lógico combinaciones de Entradas posible. Para El
soltero aporte NO puerta solo uno fila es requerido. El código es a poco laborioso,
desde En su mayoría es “ println ” Los caracteres de tabulación ( “ \t ” ) se
escriben como cadenas en lugar de caracteres (es decir, se colocan entre comillas
dobles en lugar de simples) para permitir la concatenación de cadenas en la salida.
7.5 169
Composition
público clase Tablas de verdad
{
público estático vacío principal(Cadena[] argumentos)
{
AndGate y Puerta = nuevo
AndGate(); OrGate orGate = nuevo
OrGate(); NotGate noGate = nuevo
NoGate();
// producción el columna encabezados para el Y puerta verdad tabla
[Link]("Verdad tabla para la puerta AND");
[Link]("\t0\t1");
// genera la tabla de verdad para la puerta AND
[Link]("0\t" + [Link](0,0) +
"\t" +
[Link](0,1));
[Link]("1\t" + [Link](1,0) + "\t" +
[Link](1,1));
// producción el columna encabezados para el O puerta verdad tabla
[Link]("Verdad tabla para la puerta OR");
[Link]("\t0\t1");
// genera la tabla de verdad para la puerta OR
[Link]("0\t" + [Link](0,0) + "\t" +
[Link](0,1));
[Link]("1\t" + [Link](1,0) + "\t" +
[Link](1,1));
// producción el columna encabezados para el NO puerta verdad tabla
[Link]("Verdad tabla para puerta NOT");
[Link]("\t0\t1");
// genera la tabla de verdad para la puerta NOT
[Link]("\t" + [Link](0) + "\t" +
[Link](1));
}
}
Este es el producción:
Verdad mesa para Y
puerta
0 1
0 0 0
1 0 1
Verdad mesa para O
puerta
0 1
0 0 1
1 1 1
Verdad mesa para NO
puerta
0 1
1 0
Por sí solas, las puertas tienen una utilidad limitada, pero si las combinamos en
una composición más grande podemos construir un componente útil. Un
componente muy simple es el semisumador.
170 7 Objects Working
Together …
7.5.2 Medio Sumador Componentes
Uno de el fundamental operaciones de a computadora es a llevar a cabo aritmética
en números binarios. Él poder hacer este por usando colecciones de puertas poner
juntos en particular formas. Un componente que podemos construir simplemente a
partir de puertas es el “ medio sumador ” , un componente eso es capaz a agregar
dos binario dígitos, productor a resultado y a llevar. Allá son solo cuatro posible
combinaciones de aporte pedacitos a a medio sumador, y solo tres posibles
resultados (Fig. 7.21 ).
Allá son a número de maneras de usando puertas de diferente tipos a construir
medio sumadoras, pero a simple y útil ejemplo (cual llega de Ilustrando
Computadoras por Day y Alcock) es uno que utiliza los tres tipos de compuertas que
hemos visto, es decir, las compuertas AND, OR y NOT. En la figura 7.22 se muestra un
semisumador construido a partir de estos componentes. junto con a Lenguaje
unificado de modelado diagrama del clases. Porque esto es Un ejemplo del muy
fuerte forma de agregación conocido como composición, nosotros usar a lleno
diamante para indicar la relación entre el medio sumador y sus puertas
componentes.
Nosotros poder crear a Semisumador clase en Java por haciendo él a
composición de objetos del varios Puerta clases. Regresando a nuestro anterior
discusión de si nosotros crear
Higo. 7.21 El posible Entradas a, y resultante Salidas de, a medio sumador
7.5 171
Composition
input
carry
result
input
HalfAdder
2
OrGate AndGate NotGate
Higo. 7.22 Un medio sumador compuesto por dos puertas AND, una puerta OR y una puerta
NOT junto con un diagrama de clases UML que muestra el símbolo de composición
objetos cuando se declaran o en el constructor, dado que en una relación de
composición el tiempo de vida de los componentes y la composición es el mismo,
tiene sentido crear los objetos de puerta cuando se declaran:
AndGate llevarYPuerta = nuevo
YPuerta(); YPuerta resultadoAndGate =
nuevo AndGate(); OrGate orGate = nuevo
OrGate();
NoGate noGate = nuevo NoGate();
Nosotros también tener dos Entradas y dos Salidas (representado por enteros).
Porque La mitad sumador requiere eso alguno Salidas ser usado como Entradas a
otro puertas, el Método “ setInput ” también declara alguno local variables a
aprobar estos valores entre puertas. Esta es la clase completa:
172 7 Objects Working
Together …
paquete [Link].capitulo7;
público clase Semisumador {
AndGate llevarYPuerta = nuevo YPuerta();
YPuerta resultadoAndGate = nuevo
AndGate(); OrGate orGate = nuevo
OrGate();
NoGate noGate = nuevo NoGate();
// Entradas a el medio
sumador int privado
entrada1; int privado
entrada2;
// Salidas de el medio sumador
privado int resultado;
privado entero llevar;
// establece los valores de los bits de
entrada públicos vacío
establecerEntrada(int en 1, entero
en2) {
entrada1 =
entrada1;
entrada2 =
en2;
// conseguir el llevar valor
llevar = [Link](entrada1, entrada2);
// conseguir el resultado valor
resultado = [Link]
([Link](entrada1, entrada2),
[Link](llevar));
}
// devuelve el bit de
resultado público entero
obtenerResultado() {
devolver resultado;
}
// devuelve el bit de
acarreo público entero
obtenerCarry() {
devolver llevar;
}
}
Finalmente, nosotros poder prueba nuestro Semisumador clase por haciendo un
objeto y envío datos hacia M é t o d o “ setInput ” . Este clase pruebas el tres
posible combinaciones de entrada, 1 + 1, 1 + 0 y 0 + 0. Tenga en cuenta que 1 +
0 significa lo mismo que 0 + 1 entonces producirá el mismo resultado.
7.5 173
Composition
paquete [Link].capitulo7;
público clase Prueba de HalfAdder
{
público estático vacío principal(Cadena[] argumentos)
{
// declarar a medio sumador
Semisumador media sumadora = nuevo Medio sumador();
// colocar el aporte a el medio
sumador [Link](1, 0);
// mostrar el salida resultante de el medio sumador
[Link]("Entrada a el medio sumador es 1, 0");
[Link]("Resultado de la mitad sumador es "
+ [Link]());
[Link]("Llevar valor de medio sumador
es "
+ [Link]());
// colocar el aporte a el medio
sumador [Link](0, 0);
// mostrar el salida resultante de el medio sumador
[Link]("Entrada a el medio sumador es 0, 0");
[Link]("Resultado de la mitad sumador es "
+ [Link]());
[Link]("Llevar valor de medio sumador
es "
+ [Link]());
// colocar el aporte a el medio
sumador [Link](1, 1);
// mostrar el salida resultante de el medio sumador
[Link]("Entrada a el medio sumador es 1, 1");
[Link]("Resultado de la mitad sumador es "
+ [Link]());
[Link]("Llevar valor de medio sumador
es "
+ [Link]());
}
}
Nuestro prueba clase produce el siguiente resultados:
Aporte a el medio sumador es 1,
0 El resultado del medio
sumador es 1 Acarreo valor de
medio sumador es 0 Entrada a el
medio sumador es 0, 0 El
resultado del medio sumador es
0. valor de medio sumador es 0
Entrada a el medio sumador es
1, 1 El resultado del medio
sumador es 0. valor de medio
sumador es 1
174 7 Objects Working
Together …
Input
Input
Half Half Half Half
Adder Adder Adder Adder
Half Half Half
Adder Adder Adder
Carry
Out
Higo. 7.23 A cuatro bits lleno sumador compuesto de medio sumadores y O puertas
Ejercicio 7.3
Utilizando las clases HalfAdder y OrGate existentes, escriba una clase FullAdder
que simule el siguiente diagrama de un sumador completo de 4 bits (Fig. 7.23 ,
adaptado de “ Ilustrando Computadoras ” por Día y Alcock, 1982). Prueba el
Agregador completo por usando Sirve para sumar varias combinaciones de
números de cuatro bits.
7.6 Resumen
En este capítulo, hemos aprovechado nuestro conocimiento de las clases y los
objetos para crear programas más grandes basados en diferentes objetos que se
comunican entre sí. Hemos visto diferentes ejemplos de la forma en que los
objetos pueden trabajar juntos.
7.6 Resumen 175
• asociación: dónde independiente objetos hablar a cada otro
• agregación: dónde un objeto es hecho arriba de otro objetos eso poder variar
• composición: a muy fuerte forma de agregación dónde el componente objetos son
arreglado.
Nosotros hecho alguno diseño decisiones, basado en qué tener hecho entonces
lejos, eso podría no ser Óptimo. Para ejemplo, nosotros creado dos clases
(Serpiente y Escalera) eso pareció Tienen mucho en común. ¿Quizás podrían
diseñarse de alguna manera para compartir estas características comunes? En el
próximo capítulo veremos la herencia y el polimorfismo, donde las clases pueden
basarse en clases existentes para extender y refinar sus comportamientos.
Herencia, polimorfismo y
Interfaces 8
A partir de las clases y objetos con los que hemos trabajado hasta ahora,
reconocemos que los objetos idénticos pertenecen a la misma clase, pero ¿qué
sucede con los objetos que son similares en lugar de idénticos? ¿Cómo sabemos,
por ejemplo, que un objeto en particular es un reloj en lugar de cualquier otro tipo
de objeto? Clasificamos instintivamente los objetos en el mundo a ser de a tipo,
por reconociendo qué es común entre diferente pero objetos similares. Un reloj es
cualquier cosa que indique la hora de alguna manera, independientemente de la
tecnología o la apariencia de un reloj en particular. La clase “ reloj ” abarca todo
lo que entendemos sobre el concepto general de “ reloj ” . Un tipo específico de
reloj no solo pertenece a una clase específica sino también a abstracciones de nivel
superior.
8.1 Abstracción
¿Qué tan abstracto (general) es nuestro concepto de “ reloj ” ? En otras palabras,
¿qué tan específico es nuestro concepto de “ reloj ”? colocar de criterios para
Decidir qué es o es no a ¿reloj? Es a diente de león reloj en realidad ¿Un reloj?
¿Tiene tanta “ relojidad ” como un reloj de pulsera? ¿Y un reloj de sol? ¿Un reloj
de vela? ¿Stonehenge? No son preguntas en blanco y negro, porque hay diferentes
niveles de detalle que utilizamos para clasificar las cosas, desde lo muy abstracto
(un reloj da la hora) hasta lo más definido (un reloj de examen parece empezar a
acelerarse media hora antes del final de un examen).
8.1.1 Herencia
Porque nosotros poder clasificar objetos en diferente niveles de detalle, nosotros
poder poner estos Las clases se organizan en una jerarquía de clasificación, con
los conceptos más abstractos en la parte superior y las descripciones de objetos
más detalladas en la parte inferior. En el punto más alto de dicha jerarquía,
nosotros podría poner " objeto " , nuestro mayoría abstracto idea de qué un
objeto es.
© Saltador Naturaleza Suiza Estado 2020
177
D. Parsons, Foundational Java , Textos en Ciencias de la
Computación, [Link]
178 8 Inheritance, Polymorphism and
Interfaces
Clock
Mechanical Clock Non-mechanical Clock
Analogue Clock Digital Clock Sun Dial Candle Clock
Higo. 8.1 A clasificación jerarquía demostración cómo cada tipo de reloj es " a amable de " el
clase eso hereda de
El término herencia se utiliza para indicar que a medida que descendemos en la
jerarquía, cada clase hereda todas las características de la clase superior y luego
agrega niveles adicionales de detalle, o específico de la clase comportamientos.
Cada clase es " a amable de " el clase arriba él De modo que un reloj digital es un
tipo de reloj mecánico y es un tipo de cronómetro. Figura 8.1 muestra una
jerarquía de clasificación de algunos tipos de relojes. Usamos el término “
subclase ”. y “ superclase ” para describir relaciones de herencia. Por ejemplo, “
reloj digital ” es una subclase de (hereda de) “ reloj mecánico ” . Por lo tanto, “
reloj mecánico ” es la superclase de “ reloj digital ” . Figura 8.1 utiliza la
notación UML para la herencia, que es una línea sólida con una punta de flecha
triangular que apunta desde la(s) subclase(s) a el superclase. Clases eso son más
que uno nivel aparte en el Los miembros de la misma jerarquía se conocen como “
ancestros ” y “ descendientes ” ; por ejemplo , “ , en la Fig. 8.1 El reloj es un
antepasado del reloj digital, mientras que el reloj solar es un descendiente del
reloj.
8.1.2 Polimorfismo
Uno de los aspectos más importantes de la programación orientada a objetos es el
polimorfismo, que significa “ de muchas formas ” . Aunque existen varios tipos
diferentes de polimorfismo, el más fundamental es la capacidad de diferentes
objetos de responder con un comportamiento diferente al mismo mensaje. Por
ejemplo, un objeto de reloj analógico y a Digital Reloj objeto quería tener
diferente maneras de mostrando el tiempo. El principio del polimorfismo es que el
mismo mensaje (por ejemplo, “ showTime ” ) podría enviarse a ambos objetos y
estos responderían con diferentes comportamientos específicos de la clase. Figura
8.2 muestra cómo estos diferente tipos de reloj responder a el El mismo mensaje.
8.1 179
Abstraction
Analogue
Clock
tiempo de la funcion()
Digital Clock
7:24
Higo. 8.2 Polimorfismo permite diferente tipos de objeto a responder diferentemente a el
mismo mensaje
8.1.3 La relación entre la herencia y el
polimorfismo
Como a idioma, Java siempre usos herencia porque todo Java clases heredar
automáticamente, cualquiera directamente o indirectamente, de el Objeto clase.
Figura 8.3 muestra cómo Todas las clases, ya sean clases estándar de Java o las
que escribimos nosotros mismos, heredan en última instancia de Object. La clase
Object tiene varios métodos, incluido “ toString ” , cual como nosotros tener
visto de anterior capítulos devoluciones a Cadena
Object
equals(Object)
toString()
hashCode()
Mi Clase Cadena
Higo. 8.3 A Lenguaje unificado de modelado clase diagrama demostración cómo todo Java clases heredar
de clase Objeto
180 8 Inheritance, Polymorphism and
Interfaces
representación del objeto, “ equals ” , que compara dos objetos de la misma clase,
y “ hashCode ” que, por razones que explicaremos más adelante, debe ser
consistente. con el “ es igual a ” método. Todo Java clases voluntad heredar estos
métodos, que ellos poder cualquiera usar " como es " (herencia) o anular con su
propio implementaciones (polimorfismo).
El primer ejemplo de este capítulo, que utilizaremos para explorar algunos
aspectos simples de la herencia de la clase Object, es la clase Location, que
presentamos previamente en el contexto de el Impartición del curso clase. A La
entrega del curso se realiza en lugar en a Ubicación. Este versión de el clase es
muy simple, y solo contiene tres campos (una dirección (una cadena), una
capacidad (un int) y un costo por día (un doble) y sus métodos de obtención y
establecimiento. Figura 8.4 muestra un diagrama UML de la clase Location,
incluidos los tipos de datos de los tres campos. Los tipos de datos devueltos desde
“ get ” También se muestran los métodos. Al igual que la sintaxis UML para los
tipos de datos de campo, el tipo de datos se separa del nombre del método
mediante dos puntos, donde no se muestra ningún tipo de retorno, esto se debe a
que los métodos tienen un tipo de retorno “ void ” .
Cuando nosotros crear clases en Eclipse, uno de el elementos de el " Nuevo
Java El cuadro de diálogo “Clase ” , que hemos ignorado hasta ahora, es el cuadro
de diálogo “ Superclase ”. Entrada. Figura 8.5 muestra cómo la superclase de
Ubicación tendrá como valor predeterminado la clase [Link] a menos
que proporcionemos el nombre de alguna otra clase de la cual heredar.
Aquí es el fuente código de nuestro Ubicación clase con el por defecto
superclase de [Link], cual es implícito entonces hace no necesidad a
aparecer en el clase declaración.
Figura 8.4 Los atributos y
métodos de el Ubicación clase Location
address : String
capacity : int
costPerDay : double
setAddress()
getAddress() : String
setCapacity()
getCapacity() : int
setCostPerDay()
getCostPerDay() : double
8.1 181
Abstraction
Higo. 8.5 El " Nuevo Java Diálogo de clase En eclipse voluntad por defecto Para usar
[Link] como La superclase de cualquier clase nueva que crees
182 8 Inheritance, Polymorphism and
Interfaces
8.2 Herencia de el Objeto Clase
¿Qué significa cuando decimos que todas las clases en Java heredan en última
instancia de Object? En un nivel simple, significa que todos los métodos de la
clase Object se heredan automáticamente. disponible a cualquier clases eso
nosotros crear. En Java nosotros especificar eso uno
8.2 Inheriting from the 183
Object Class
La clase hereda de otra mediante el uso de " extiende " Palabra clave. Si no
especifica la clase de cual su propio clase hereda, él automáticamente valores
predeterminados a extendiendo Object. La declaración de la clase Location podría,
de hecho, haberse escrito como
Pero esto no era necesario porque es la opción predeterminada. Sin embargo, si
queremos heredar de clases distintas de Object, entonces debemos indicarlo
explícitamente, como veremos en ejemplos posteriores de este capítulo.
Nota
Java solo apoya soltero herencia, cual medio eso a Java clase debe heredan
directamente de sólo otra clase.
Antes de analizar el polimorfismo, comenzaremos con algunos conceptos
básicos de herencia. Ya sabemos que los objetos tienen un atributo “ toString ”
predeterminado. método. Esto se hereda de la clase Object y devuelve el
nombre de clase completamente calificado del objeto junto con el picadillo código
de es memoria DIRECCIÓN. Nosotros tener también visto en anterior Ejemplos
del efecto de comparar dos objetos utilizando el operador “ == ” . Esto devuelve “
verdadero ” solamente si el dos objeto referencias punto a exactamente el mismo
objeto. El actual estado de los objetos se ignora. La implementación
predeterminada del método “ equals ” , también heredado de Object, hace lo
mismo.
Aquí hay un método principal que demuestra tres objetos de ubicación que
heredan el " toString ". y “ es igual ” Métodos de la clase Object. Recuerde que “
toString ” se llama implícitamente cada vez que se coloca un objeto en una
instrucción “ [Link] ” . Dos de los objetos Location tienen el mismo
estado (todos sus campos están configurados con valores idénticos), pero, de
manera predeterminada, no se considerarán iguales:
184 8 Inheritance, Polymorphism and
Interfaces
El producción de este programa es bastante feo pero refuerza qué nosotros ya
conocer los objetos; su “ toString ” predeterminado muestra el nombre del
objeto y el paquete, y cada objeto tiene a diferente picadillo código derivado de es
memoria DIRECCIÓN. También, si Nosotros comparamos dos objetos eso tener
diferente memoria direcciones, ellos son no igual, incluso si tienen el mismo
estado (el mensaje de desigualdad se ha resaltado en texto negrita).
8.2 Inheriting from the 185
Object Class
8.2.1 Primordial el “aCadena” Método
A pesar de el por defecto versión de “ aCadena ” es heredado de clase Objeto por
todo otras clases, ya hemos visto algunas clases Java que implementan “ toString
” de una manera diferente. forma, para ejemplo el Cadena y Fecha clases. Estos
versiones de “ toString ” son polimórfico; ellos anular el por defecto
Implementaciones con unos más Adecuado para esas clases. También podemos
proporcionar versiones especializadas de “ toString ”. para nuestras propias clases
escribiendo un método con la misma firma (visibilidad, nombre, tipo de retorno y
lista de parámetros) que el de la clase Object, es decir:
A partir de esta firma, podemos ver que el “ toString ” El método es público y
devuelve una cadena. y acepta No parámetros. Aquí, nosotros proporcionar
nuestro propio versión de el método para objetos de ubicación. Funciona
concatenando el nombre de clase simple (del objeto de clase), la dirección, la
capacidad y el precio, junto con algunas etiquetas de texto adecuadas, en un único
objeto String y luego devolviendo esa String desde el método:
Un “ toString ” El método se puede escribir de cualquier forma que desee,
según cómo se vaya a utilizar. Además de proporcionar una cadena que se puede
mostrar en una interfaz de usuario, también puede ser útil para el registro y el
diagnóstico, ya que nos permite representar cualquier aspecto de un objeto estado
como a Cadena usando a método eso es Accesible desde cualquier objeto. Aquí se
muestra el resultado del mismo programa de prueba después de agregar el método
“ toString ” a la clase Location.
186 8 Inheritance, Polymorphism and
Interfaces
8.2.2 Primordial el “es igual a” Método
Ciertamente, la salida de nuestro código de prueba es más legible cuando utiliza la
versión polimórfica de “ toString ” , pero ¿qué pasa con el hecho de que las dos
ubicaciones con el mismo estado son no ¿igual? Uno opción nosotros tener en
Java es a anular el El método “ equals ” permite comparar el estado de los objetos
en lugar de sus direcciones. Al igual que con “ toString ” , nosotros poder anular
el heredado implementación por escribiendo nuestro propio Versión del método
con la misma firma. La firma del método “ equals ” es:
En nuestro propio implementación nosotros debe asegurar eso si el parámetro
objeto es nulo, o el parámetro objeto es no de el adecuado clase a hacer a
comparación, nosotros devuelve “ falso ” . De lo contrario, nosotros son gratis a
implementar nuestro definición de igualdad basado en El estado de el objetos. En
este ejemplo, nosotros comenzar por regresando " FALSO " si el parámetro es
nulo o no un objeto de el mismo clase como el uno hospedaje el método. Si
nosotros conseguir Más allá de esto prueba, nosotros entonces comparar el dos
objetos, después fundición el parámetro Objeto a el tipo de clase real (tenga en
cuenta que la conversión de tipos de objetos utiliza la misma sintaxis que la
conversión de primitivos) tipos). Si ellos tener el mismo DIRECCIÓN, capacidad
y precio datos entonces ellos se consideran iguales y devolvemos “ verdadero ” ,
de lo contrario devolvemos “ falso ” .
Si nosotros agregar este método a el Ubicación clase y correr el prueba código
de nuevo, entonces esta vez Aulas 2 y 3 son mostrado a ser igual (el igualdad
mensaje es resaltado en negrita):
8.2 Inheriting from the 187
Object Class
8.2.3 Primordial el “Código hash” Método
Si reemplazamos el método “ equals ” , entonces también debemos reemplazar el
método “ hashCode ” . Esto se debe a que “ equals ” y “ hashCode ” deben ser
consistentes entre sí. En sus implementaciones predeterminadas, tanto “ equals ”
como “ hashCode ” se relacionan con la dirección de memoria del objeto. Si
reemplazamos “ igual ” Para basarse en el estado del objeto en lugar de en su
dirección, entonces “ hashCode ” También se debe anular para que se
base en el mismo estado . Aquí se muestra una implementación del código
hash Método para la clase Location. El método debe devolver un entero. En este
método reutilizamos el código “ hashCode ”. de la clase String (String ya anula el
método “ hashCode ” ) y luego agregue la capacidad y el precio (convertido a un
int) para devolver el código hash.
El razón para haciendo el “ Código hash ” método usar el mismo datos como
el método “ igual ” es eso este es requerido Cuando un objeto es indexado en a
picadillo mesa, cual es una estructura de datos que almacena objetos mediante
claves. La implementación de la búsqueda de objetos utiliza tanto el " igual " y “
hashCode ” métodos, por lo que deben basarse en los mismos datos.
Para ver los resultados del código hash polimórfico método, se pueden
agregar las siguientes tres líneas al código de prueba para mostrar los códigos
hash:
Aquí está el resultado. Observe cómo se muestran los códigos hash de las aulas
dos y tres. idéntico.
188 8 Inheritance, Polymorphism and
Interfaces
A pesar de nuestro implementación es probable a generar único picadillo
códigos para Si bien los objetos tienen un estado único, no hay garantía de que
siempre lo tengan. Esto no es un problema, ya que es aceptable que los objetos
tengan el mismo código hash, incluso cuando se almacenan en una tabla hash. Sin
embargo, existe el peligro de anular los valores iguales y el código hash. en este
forma para objetos eso puede cambiar su estado. El picadillo código voluntad
cambia si se actualizan los campos del objeto . Por este motivo, un objeto con
este tipo de método “ hashCode ” no debería modificarse mientras se encuentre
en una tabla hash.
8.2.4 Generando “Código hash” y “es igual a”
Métodos en Eclipse
Porque es tan importante el “ hashCode ” y “ es igual ” Los métodos se
actualizan juntos. Eclipse proporciona una herramienta integrada para hacerlo.
Mientras edita la clase, simplemente seleccione " Fuente " ! " Generar código
hash() y es igual a() …” y el implementación Se generarán ambos métodos en
función de los campos que elija en el cuadro de diálogo. Nosotros voluntad no
incluir el generado código aquí, pero si tú intentar él afuera para Usted mismo verá
que la implementación generada es considerablemente más detallada y compleja.
que el bastante básico Implementaciones eso tener estado mostrado en este
capítulo. Sin embargo, cómo desea definir la igualdad de sus objetos depende de
usted.
8.2.5 El @Anular Anotación
Anotaciones en Java usos a colocar de “ metaetiquetas ” eso relatar a metadatos
(datos acerca de datos). Un anotación es precedido por el “ @ ” símbolo. Uno de el
más simple anotaciones a El uso es “ @Anular ” cual nosotros poder poner antes
cualquier métodos eso están destinados a métodos de anulación en a superclase. A
grande ventaja de haciendo este es eso si a método es Si se anota de esta manera
pero no se anula un método de la superclase, el compilador generará un mensaje
de error. Esto garantiza que hemos anulado correctamente los métodos. eso
nosotros pretender a. Para ejemplo, nosotros podría hacer a error en el firma del
método “ toString:”, quizás utilizando una “ s ” minúscula .
El problema aquí es eso este es no a compilador error. El compilador
simplemente trata esto como si fuera un método diferente de “ toString ” , por lo
que no será polimórfico. Sin embargo, si nosotros agregar el “ @Anular ”
anotación antes el método, el compilador nos dirá que no estamos anulando
ningún método de la superclase:
8.2 Inheriting from the 189
Object Class
Este es a muy útil ayuda a asegurando eso nuestro métodos son como
polimórfico como Esperamos que así sea, por lo que es una buena práctica utilizar
“ @Override ”. anotación en todos los métodos que anulan los métodos de la
superclase.
Ejercicio 8.1
Agregue los métodos “ toString ” , “ equals ” y “ hashCode ” a la clase Course
del curso anterior. capítulo. Recordar eso su Implementaciones de “ es igual a ” y
El “ código hash ” se puede hacer de cualquier forma que desees, pero debe ser
coherente entre sí. Opcionalmente, tú poder generar estos métodos usando el
Eclipse " Fuente " menú elemento. Escribe una clase con un “ principal ” Método
que crea un objeto Course y demuestra estos métodos. Utilice la anotación
@Override al escribir estos métodos.
8.3 Un Herencia Jerarquía Usando Abstracción
En este capítulo, nosotros tener miró cómo todo Java clases, si proporcionó en a
Paquete Java o escrito por nosotros mismos, heredan de (son subclases de) Object.
También podemos heredar de nuestro propio clases a agregar extra funcionalidad
a un existente clase e implementar los métodos polimórficos. En el siguiente
ejemplo, crearemos una jerarquía de formas. Este es un ejemplo de herencia muy
común y hay muchas formas diferentes de crear una jerarquía de este tipo. De
hecho, Java mismo proporciona algo similar en el paquete “ [Link] ” . Sin
embargo, el propósito de este ejemplo no es intentar producir una jerarquía
completa o incluso “ correcta ” de formas, sino simplemente usar el ejemplo para
explorar algunos aspectos importantes de la herencia y el polimorfismo. La
jerarquía de formas utilizada en este capítulo está diseñada en torno a conceptos
genéricos de forma, tratando de no violar el principio de sustitución de Liskov.
cual es a equitativamente complejo concepto pero, simplemente poner, dice eso un
objeto de Una subclase debería poder reemplazar un objeto de una superclase sin
afectar ninguna otra parte del código. Tal vez sea tentador construir una jerarquía
de formas de Java en torno a la reutilización de código. Los métodos de dibujo de
Java para formas simples (en lugar de líneas y arcos) se basan en rectángulos,
óvalos, polígonos y rectángulos redondeados. Sin embargo, construir una jerarquía
basada simplemente en intentar reutilizar estos métodos de dibujo a través de la
herencia pondría a los círculos y óvalos en la misma parte de la jerarquía, al igual
que a los cuadrados y rectángulos. Esto causa algunos problemas interesantes; por
ejemplo, ¿es Square una subclase de Rectangle? ¿O es Rectangle una subclase de
Square? Ciertamente, hacer de Square una subclase de Rectangle viola el principio
de sustitución de Liskov. desde a Cuadrado no puedo tener es lado longitudes
independientemente cambió, pero Difícilmente podemos decir que un rectángulo
es un tipo de cuadrado. Esta cuestión no es importante en sí misma, pero sirve para
subrayar un aspecto importante del diseño de jerarquías de herencia, que es que no
deben diseñarse en torno a un deseo de reutilizar el código. Más bien, debemos
buscar algo que funcione bien desde la perspectiva del conjunto. diseño objetivos
nosotros tener en nuestro solicitud, lo que ellos puede ser. El
190 8 Inheritance, Polymorphism and
Interfaces
Forma
Ubicación: Dimensiones
del punto : entero[]
obtenerDimension
es()
Forma unidimensional se extiende Forma
OneDimensionalShape
Círculo se extiende Forma unidimensional
Circle
Higo. 8.6 Forma es el superclase de Forma unidimensional, cual en doblar es el superclase
de circulo
acercarse usado aquí (de muchos nosotros podría tener preferido) es basado en el
Propiedades dimensionales de simple formas, con a básico clasificación de formas
en aquellos eso tienen una dimensión de medida y los que tienen dos.
Figura 8.6 muestra a parte (a vertical rebanada) de el herencia jerarquía eso
nosotros se utilizará en este ejemplo. Dado que OneDimensionalShape es una
subclase (especialización) de Shape, y Círculo es a subclase de Forma
unidimensional, Círculo voluntad heredar todo los campos y métodos de
OneDimensionalShape, que a su vez hereda todos los campos y métodos de
Shape , por lo que Circle finalmente hereda también de Shape. Shape y
OneDimensionalShape son superclases o generalizaciones de Circle.
Figura 8.6 sólo muestra algunas características de las clases, que
desarrollaremos con más detalle a lo largo de las siguientes secciones.
Anteriormente, solo hemos estado heredando de la clase Object, por lo que
heredamos solo la métodos de eso clase. Sin embargo, en este jerarquía, mientras
Forma voluntad ser a subclase de Object, OneDimensionalShape hereda de Shape
y Circle hereda de OneDimensionalShape. Para el Propósitos de este ejemplo, a
OneDimensionalShape es uno eso poder ser representado usando a soltero
dimensión, semejante como el radio de a círculo o el lado longitud de a cuadrado,
mientras que un Forma bidimensional quería ser uno que encajaría dentro de un
cuadro delimitador rectangular con dos dimensiones (por ejemplo, rectángulos,
óvalos, rectángulos redondeados, etc.). En cada nivel de la jerarquía, la clase
extenderá explícitamente la clase de la que hereda:
8.3 An Inheritance Hierarchy Using 191
Abstraction
La forma tiene un campo de “ ubicación ” (una instancia de
[Link]) y un campo de dimensión, cual es un formación de
números enteros. Estos campos voluntad ser heredado por el subclases, aunque
dependiendo de su visibilidad pueden no ser directamente accesibles en las
subclases. En otras palabras, un “ Círculo ” tendrá “ ubicación ” campo como
parte de su estado, pero no podrá acceder a él directamente si está marcado como "
privado " . Hay varias formas de abordar esta cuestión, que exploraremos más
adelante.
8.3.1 Abstracto Clases
Todas las clases que hemos creado en nuestros ejemplos anteriores han sido clases
concretas. Esto significa que podemos instanciar (crear instancias de) objetos de
estas clases. Una clase abstracta, por otro lado, es una que no se puede instanciar.
Las clases abstractas se dan en jerarquías de herencia, donde cumplen funciones
de generalización. eso clasificar por categorías cierto tipos de objeto pero hacer no
representar el detalles Se requiere un objeto que se pueda crear de manera útil. En
nuestra jerarquía de formas, tanto Shape como OneDimensionalShape son
abstracciones, bastante que descripciones de concreto formas. No tiene sentido
tener una instancia de Shape o OneDimensionalShape, aunque quería esperar a
ser capaz a crear instancias de, para ejemplo, el Círculo Clase.A clase eso se
extiende un abstracto clase, y cual es no abstracto sí mismo, es dicho a ser una
implementación concreta de la clase abstracta; Circle es una implementación
concreta de la OneDimensionalShape abstracta.
La “ Nueva Clase Java ” El cuadro de diálogo en Eclipse incluye una opción
para crear una clase abstracta (Higo. 8.7 ). Sin embargo, el solo efecto de este
caja es a agregar el " abstracto "
Higo. 8.7 Creando un abstracto clase en Eclipse (de cheques el " abstracto " caja)
192 8 Inheritance, Polymorphism and
Interfaces
palabra clave a la declaración de clase, por lo que se puede agregar o cambiar
fácilmente en el archivo fuente.
8.3.2 Protegido Visibilidad y Herencia
Como se mencionó anteriormente, los campos (y métodos) privados son heredados
por las subclases, pero son no de hecho visible a a ellos. Este medio eso, para
ejemplo, si el " ubicación " campo de la “ Forma ” Si la clase tiene visibilidad
privada, entonces cualquier objeto de una subclase de Shape tendrá un campo de
ubicación, pero los métodos de la subclase no podrán acceder a él directamente.
Un enfoque alternativo es marcar estos campos como " protegidos " . Esto los
convierte directamente en accesible a subclases en cualquier paquete y, también, a
cualquier otro clases en el mismo paquete. Por ejemplo, los campos “ ubicación ”
y “ dimensión ” de “ Forma ” podrían tener visibilidad protegida.
Este tipo de visibilidad está específicamente diseñado para usarse en jerarquías
de herencia y permite subclases a campos de acceso y métodos que tener estado
heredado de una superclase. De hecho, la visibilidad protegida es algo más abierta
que la visibilidad del paquete (por defecto) ya que un elemento protegido es
visible a través de su propio paquete, como así como a subclases en otro paquetes.
Dado eso todo el código en este ejemplo es en un paquete, podríamos haber usado
igualmente visibilidad de paquete, pero usar visibilidad protegida da una mejor
declaración de intenciones ya que deja claro que estos elementos están destinados
a ser accesibles a las subclases.
Calificación campos como “ protegido ” hace, sin embargo, romper
encapsulamiento a alguno extensión por haciendo campos directamente visible no
solo a subclases pero a todo clases en el mismo paquete. Otro enfoque, que
mantiene la encapsulación, es dejar los campos " privados " pero proporcionarles
métodos de acceso públicos o protegidos. En este ejemplo, nosotros voluntad
demostrar el usar de protegido campos pero oso en mente eso Se podrían haber
tomado otras decisiones de diseño sobre la visibilidad de los atributos (y métodos).
Aquí es el Forma clase con protegido campos y público métodos.
8.3 An Inheritance Hierarchy Using 193
Abstraction
8.3.3 Creando Subclases
Creando a subclase en Java es simplemente a pregunta de añadiendo el “ se
extiende ” palabra clave hacia clase declaración con el adecuado superclase
nombre. El superclase poder También ser seleccionado en Eclipse en el " Nuevo
Java Clase " diálogo. Tú poder cualquiera tipo el nombre de la clase en el campo
de texto “ Superclase ” , o presione el botón “ Explorar ” , que buscará para
clase nombres eso fósforo qué tú tipo en el arriba de el diálogo (Higo. 8.8 ). En
este ejemplo, la clase OneDimensionalShape se crea como una subclase de Shape.
Nuevamente, es necesario marcarla como “ abstracta ” .
194 8 Inheritance, Polymorphism and
Interfaces
Higo. 8.8 Seleccionar una superclase en Eclipse
Como antes, el efecto en el generado código de estos diálogo Opciones es
mínimo, De esta forma, las palabras clave necesarias se pueden introducir
manualmente en el código fuente si es necesario. La declaración de clase de la
clase OneDimensionalShape debería verse así, utilizando las palabras claves “
abstract ” y “ extends ” .
Qué métodos, entonces, son adecuado a este abstracto ¿clase? Allá son a pareja
de posibilidades descritas Aquí uno es que podríamos querer cualquier forma
unidimensional ser capaz a devolver es soltero dimensión, cual quería ser
almacenado en el primero elemento de la matriz “ dimensiones ” . El siguiente
método devolvería este valor.
Más interesante aún, existe un problema potencial con la versión de superclase
de “ setDimensions ” , porque él quería permitir un arbitrario formación a ser
colocar. El Los siguientes métodos anulan esta versión de la superclase para
garantizar que solo se pueda usar una matriz con un solo valor. poder ser usado a
cambiar el dimensión de el forma. Nota el usar de el Palabra clave “ super ” en este
ejemplo. Llama explícitamente a la versión de superclase de “ setDimensions ”.
método. Este es básico a prevenir el “ establecerDimensiones ” método
8.3 An Inheritance Hierarchy Using 195
Abstraction
llamándose a sí mismo en un bucle recursivo. Por lo tanto, la distinción entre usar
“ super ” y “ this ” implícito es muy importante.
8.3.4 Vocación Superclase Constructores
En ejemplos anteriores vimos que podíamos encadenar constructores dentro de un
solo clase, usando " este( … ) " . A similar técnica poder ser usado en el
constructores de un herencia jerarquía. A llamar el constructor de a superclase,
nosotros poder hacer a Llamar a " súper( … ) " . Como a recordatorio, aquí es el
constructor de el Forma clase, cual Establece la ubicación de la forma a partir del
argumento del parámetro Punto.
El constructor OneDimensionalShape también necesita establecer la posición
de la forma. en es constructor, pero nosotros hacer no desear a tener el mismo
código repetido aquí, Así que nosotros hacer el llamar a el superclase constructor,
a reutilizar el existente implementación. Es esencial que la lista de argumentos de
parámetros pasados en la llamada a “ super ” coincida con uno de los
constructores que se han definido para la superclase.
Nota
Si tú hacer no llamar el superclase constructor explícitamente allá voluntad ser
un implícito Llamar a " súper(), " eso es, a cero argumentos constructor en el
superclase. Si este hace no existe obtendrá errores de compilación.
En el resto del constructor, necesitamos crear la matriz y establecer el (único)
dimensión de el forma. Nota eso alguno interno encapsulamiento es usado Aquí.
Más bien que directamente Accediendo el “ dimensiones ” campo, a temporario
formación se crea,
196 8 Inheritance, Polymorphism and
Interfaces
utilizando el valor del parámetro en una lista de inicializadores. Esta matriz se
pasa luego a “ setDimensions ” método. Como hemos comentado en ejemplos
anteriores, este tipo de encapsulación interna puede ayudarnos a mejorar la
robustez de nuestro código al garantizar que cualquier comprobación de errores
que introduzcamos en el “ setDimensions ” Los métodos siempre se llaman.
Aquí es el completo Forma unidimensional clase con el métodos y
constructor que hemos discutido previamente.
8.3 An Inheritance Hierarchy Using 197
Abstraction
Como nosotros ir más abajo el jerarquía a el concreto clases, el mismo proceso
de constructores que llaman a los de la superclase se repite. Por ejemplo, el
constructor Circle llamadas es propio superclase constructor en el Forma
unidimensional clase. Aquí, se pasan dos argumentos de parámetros al constructor
de la superclase: la ubicación y el radio.
Ejercicio 8.2
Dado el clases Discutido entonces lejos (Forma, Forma unidimensional y Círculo),
escribe un clase con a " principal " método eso crea un instancia de el Círculo
clase y usos sus métodos heredados, “ setDimensions ” y “ getDimension ” .
8.3.5 Añadiendo Más Subclases
Nosotros voluntad ahora doblar nuestro atención a el Forma bidimensional clase,
cual tiene Algunas diferencias con OneDimensionalShape. Nuevamente, el
constructor crea una matriz local a partir de los parámetros de dimensión que se le
pasan, pero en este caso, hay dos dimensiones, en lugar de una. Como antes, luego
llama al constructor de la superclase. Contiene métodos de utilidad para sus
propias subclases que son relevantes para las formas en un cuadro delimitador
rectangular. En esta clase, los dos primeros elementos de la matriz “ dimensiones
” están disponibles a través de los métodos “ getHeight ” y “ getWidth ” ,
nuevamente encapsulando el acceso a la matriz subyacente. Tiene una
implementación diferente de “ setDimensions ”. método, de cheques eso el
parámetro formación tiene dos elementos. Aquí hay una clase completa.
198 8 Inheritance, Polymorphism and
Interfaces
Uno de el concreto subclases de Forma bidimensional es el Rectángulo clase.
Al igual que Circle, llama a su propio constructor de superclase, en este caso
desde la clase TwoDimensionalShape. Aquí, se pasan tres parámetros al
constructor de la superclase: la ubicación, la altura y el ancho.
8.3 An Inheritance Hierarchy Using 199
Abstraction
Ejercicio 8.3
Escribe una clase con un “ main ” método que crea una instancia de la clase
Rectangle y utiliza sus métodos heredados, “ setDimensions ” , “ getWidth ” y “
getHeight ” .
8.4 Dinámica Vinculante y Abstracto Métodos
Aunque en términos generales, el polimorfismo es el uso del mismo nombre de
método en diferentes clases, estos clases son generalmente en el mismo herencia
jerarquía. Este es porque nos permite implementar un tipo de polimorfismo
conocido como enlace dinámico . Este es basado en el capacidad de a superclase
referencia a punto a un objeto de una subclase. Hemos visto en todas nuestras
llamadas anteriores a un constructor de objetos que la referencia a un objeto ha
sido del mismo tipo que el objeto mismo. Por ejemplo, para crear un objeto Circle
esperaríamos utilizar una referencia de la clase Circle:
Sin embargo, una referencia de una superclase se puede utilizar para hacer
referencia a un objeto de cualquier subclase, por lo que si nuestra clase Circle es
una subclase de Shape, podemos utilizar una referencia Shape para apuntar a un
objeto Circle.
Este es un truco útil para soportar el polimorfismo; podemos usar la referencia
de superclase como una forma de invocar métodos polimórficos en objetos de
subclases. voluntad ver, este da a nosotros flexibilidad cuando creando el
control estructuras de programas que manejan cantidades de objetos polimórficos.
La principal restricción aquí es que solo podemos invocar un método en el
objeto si ese método aparece en la interfaz pública de la superclase. Por ejemplo,
si la clase Circle tiene un método “ getArea ” que devuelve el área del círculo,
entonces Shape también debe tener un método “ getArea ”. método, o no
podemos invocar el método en la referencia, incluso aunque él es disponible en el
objeto, para ejemplo, este método llamar En una forma debe ser válido:
En la Fig. 8.9 , tenemos dos métodos adicionales en la clase Circle, “ getArea ”
(que devoluciones el área de el círculo como a doble) y " dibujar " (cual usos a
[Link]. Objeto gráfico para dibujar en la pantalla) que se aplican a esa clase pero
que no se han aplicado a la clase Shape. Para que sea posible invocar estos
métodos polimórficos usando a referencia de tipo Forma, nosotros necesidad a
agregar ambos métodos a el Clase de forma .