Modulo 6
Modulo 6
Modulo 6
Temas
RECORDANDO
HERENCIA: UN PRIMER ACERCAMIENTO
MI NOVENA APP
HERENCIA: SOBRE-ESCRITURA DE MÉTODO
MI DECIMA APP
HERENCIA: CLASE ABSTRACTA
MI DECIMA PRIMERA APP
INTERFACE
MI DECIMO SEGUNDA APP
TALLER
REFERENCIAS
RECORDANDO
programación modelada con base en la forma como funciona el mundo real: objetos con
objetos, cada uno de los cuales representa una instancia de alguna clase, y cuyas clases son
Encapsulamiento
Composición
Polimorfismo
Herencia
Clase abstracta
Interface
Se dice que, si alguno de estos elementos no existe, entonces el modelo no es orientado a
Por último, se aborda las denominadas interfaces como una forma de reemplazar la
prestado de la Biología donde se afirma que un niño tiene la cara de su padre, que ha
como el C++ o Java, de otro convencional como C, BASIC, etc. Java permite heredar a una
clase características y conductas de otra clase denominada base. Las clases que heredan
de clases base se denominan derivadas, estas a su vez pueden ser clases bases para otras
La herencia ofrece una ventaja importante, permite la reutilización del código. Una vez que
una clase ha sido depurada y probada, el código fuente de dicha clase no necesita
modificarse. Su funcionalidad se puede cambiar derivando una nueva clase que herede la
existente, el programador ahorra tiempo y dinero, ya que solamente tiene que verificar la
Cuando se dan cuenta que diversos tipos tienen algo en común, por ejemplo, en el juego
del ajedrez peones, alfiles, rey, reina, caballos y torres, son piezas del juego. Creamos,
por tanto, una clase base y derivamos cada pieza individual a partir de dicha clase base.
código existente.
3
Por seguridad en el código Java NO permite la herencia múltiple, es decir, que una clase
herede de varias clases (el lenguaje C++ si lo permite). Para resolver las ventajas de la
este módulo.
sólo se considerarán tres de éstos: poleas, bloques recangulares y ruedas. Para simular este
Para simular el movimiento de los cuerpos rígidos debe pensarse en que todo cuerpo rígido
puede trasladarse y/o rotar alrededor de un eje que pasa por su centro de masa. Todos
tienen el atributo masa y momento de inercia (que no se agregarán en este ejemplo para no
como el color, entre otros (grosor de línea, color de los bordes…, que no se agregarán en
este ejemplo para no dificultar su comprensión) y necesitan del método que los dibuje.
respectivo para lograr esto. Con base en este análisis se puede pensar en diseñar una clase
madre que tenga estos atributos y comportamientos comunes a todos los cuerpos rígidos y
Para poderse dibujar los objetos de las clases Polea y Rueda necesitarán adicionalmente
el atributo radio y los ojbetos tipo CuerpoRectangular necesitarán los atributoa largo y
alto. Estas clases heredarán de CuerpoRigido y agregarán o implementarán sus
Figura 1
método dibujese( ), éste será incluido en las clases hijas. En las siguientes dos apps se
inclusión a través del concepto de clase abstracta. En la última app de este módulo este
Clase CuerpoRigido:
/**
* Constructor por defecto del cuerpo rígido.
* Su centro de masa está ubicado en la
* posición (0,0). La posición angular es cero
* y su color es rojo
*/
public CuerpoRigido() {
/**
* Constructor de CuerpoRigido
* cuyo centro de masa está
* ubicado en (posicionInicialX,posicionInicialX)
*/
/**
* Modifica el color del cuerpo rígido
*
* @param color
*/ 5
public void setColor(int color) {
this.color = color;
}
/**
* Devuelve el color del cuerpo rígido
*
* @return
*/
public int getColor() {
return color;
}
/*
Se podría hacer un método setPosicion(x,y)
para cambiar la posición del centro de masa, pero más adelante
esta el método mover(x,y) que hace esto
*/
/**
* Retorna la posicion en X
* del centro de masa
*
* @return
*/
return posicionCentroMasaX;
}
/**
* Retorna posicion en Y
* del centro de masa
*
* @return
*/
public float getPosicionY() {
return posicionCentroMasaY;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido
*
* @param posicionCentroMasaX
* @param posicionCentroMasaY
*/
public void mover(float posicionCentroMasaX, float
posicionCentroMasaY) {
this.posicionCentroMasaX = posicionCentroMasaX;
this.posicionCentroMasaY = posicionCentroMasaY;
/** 6
* Modifica la posición angular del cuerpo rígido
* alrededor de une eje uqe pasa por su centro
* de masa
*
* @param posicionAngular
*/
public void mover(float posicionAngular) {
// this.posicionAngularRotacionCentroMasa = posicionAngular;
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido y genera una rotación
* alrededor del eje que pasa por éste
* @param posicionCentroMasaX
* @param posicionCentroMasaY
* @param posicionAngular
*/
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Genera rotación del cuerpo rígido a la
* posición angular posicionAngularRotacionEjeXY
* alrededor de eje que pasa por
* (posicionEjeRotacionX,posicionEjeRotacionY)
* @param posicionEjeRotacionX
* @param posicionEjeRotacionY
* @param posicionAngular
*/
this.posicionAngularRotacionEjeXY=posicionAngular;
7
Clase Polea:
/**
* Constructor por defecto
* Polea centrada en (0,0)
* y de radio 50f
*/
public Polea() {
super();
this.radio = 50f;
}
/**
* Constructor de Polea centrada
* en (posicionX,posicionY)
* y diámetro igual a 2*radio
*/
/**
* Modifica el valor del radio de la polea
*
* @param radio
*/
public void setRadio(float radio) {
this.radio = radio;
}
/**
* Devuelve el valor del radio de la polea
*
* @return
*/
public float getRadio() {
return radio;
}
canvas.save();
//rotar
canvas.rotate(posicionAngularRotacionEjeXY,posicionEjeRotacionX,posic
ionEjeRotacionY);
//dibujar circunferencia de la polea
canvas.drawCircle(posicionCentroMasaX, posicionCentroMasaY,
radio, pincel);
//dibujar las líenas radiales de la polea
for (int i = 0; i < 12; i = i + 1) {
//rotar de a 36 grados
canvas.rotate(i * 36f, posicionCentroMasaX,
posicionCentroMasaY);
canvas.drawLine(posicionCentroMasaX, posicionCentroMasaY,
posicionCentroMasaX, posicionCentroMasaY - radio, pincel);
//retroceder la rotación
canvas.rotate(-i * 36f, posicionCentroMasaX,
posicionCentroMasaY);
}//fin for
//regresar la rotación
canvas.restore();
}
Clase Rueda:
/**
* Constructor por defecto
* Rueda centrada en (0,0)
* y de radio 50f
*/
public Rueda() {
super();
this.radio = 50f;
}
/**
* Constructor de Rueda centrada
* en (posicionCentroMasaX,posicionCentroMasaY)
* y diámetro igual a 2*radio 9
*/
/**
* Modifica el valor del radio de la rueda
*
* @param radio
*/
public void setRadio(float radio) {
this.radio = radio;
}
/**
* Devuelve el valor del radio de la rueda
*
* @return
*/
public float getRadio() {
return radio;
}
canvas.save();
//rotar
canvas.rotate(posicionAngularRotacionEjeXY,posicionEjeRotacionX,posic
ionEjeRotacionY);
//dibujar círculo de la rueda
pincel.setStyle(Paint.Style.FILL);
canvas.drawCircle(posicionCentroMasaX, posicionCentroMasaY,
radio, pincel);
pincel.setColor(Color.BLACK);
//dibujar punticos negro para poder bservar la rotación de la
rueda
//regresa la rotación
canvas.restore();
Clase CuerpoRectangular:
/**
* Constructor por defecto
* Bloque centrado en (0,0)
* de largo 150f y de alto 100f
*/
public CuerpoRectangular() {
this.largo = 150f;
this.alto = 100f;
}
/**
* Constructor de cuerpo rectangular
* centrado en (posicionCentroMasaX,posicionCentroMasaY)
* de dimensiones largoxalto
*/
/**
* Modifica el valor del largo del cuerpo
* rectangular *
* @param largo
*/
public void setLargo(float largo) {
this.largo = largo;
} 11
/**
* Devuelve el valor del largo del cuerpo
* rectangular
*
* @return
*/
public float getLargo() {
return largo;
}
/**
* Modifica el valor del ancho del cuerpo
* rectangular
*
* @param alto
*/
public void setAlto(float alto) {
this.alto = alto;
}
/**
* Devuelve el valor del alto del cuerpo
* rectangular
*
* @return
*/
public float getAlto() {
return alto;
}
canvas.save();
//rotar
canvas.rotate(posicionAngularRotacionEjeXY,posicionEjeRotacionX,posic
ionEjeRotacionY);
//dibujar el relleno del bloque
pincel.setStyle(Paint.Style.FILL);
canvas.drawRect(posicionCentroMasaX-0.5f*largo,
posicionCentroMasaY-0.5f*alto,posicionCentroMasaX+0.5f*largo,
posicionCentroMasaY+0.5f*alto, pincel);
//dibujar el perímetro del bloque
pincel.setColor(Color.BLACK);
pincel.setStyle(Paint.Style.STROKE);
canvas.drawRect(posicionCentroMasaX-0.5f*largo,
posicionCentroMasaY-0.5f*alto,posicionCentroMasaX+0.5f*largo,
posicionCentroMasaY+0.5f*alto, pincel);
//regresar la rotación 12
canvas.restore();
MI NOVENA APP
Paso 1:
Con Android Studio craer un proyecto denominado MiNovenaApp (recordar que el proyecto
se debe crear tal cual se ha venido desarrollando los proyectos en el curso) y crear las
clases y paquetes que den la estructura de la Figura 2. A las clases del paquete
13
/**
* Constructor
*
* @param context
*/
public Pizarra(Context context) {
super(context);
this.poleas = poleas;
this.ruedas = ruedas;
this.cuerposRect = cuerposRect;
} 14
if (poleas != null)
dibujarEscena(canvas, pincel);
@Override 15
public void run(){
corriendo = true;
while (corriendo==true){
try {
Thread.sleep(periodo_muestreo);//esto en milisegundos
} catch (InterruptedException e) {
e.printStackTrace();
}
tiempo=tiempo+0.01f;
//cambio de estado de la escena física en la pizarra
cambiarEstadosEscenaPizarra(tiempo);
//polea_1
/*La polea 1 arranca de la posición x=100 y=100
Se traslada con velocidad constante en x Vx=200; Vy=0;
No rota alrededor de su eje, W=0
*/
float x_1= 100 + 200*tiempo;
float y_1=100;
//polea_2
/*La polea 2 se arranca de la posición x=100 y=250
No se traslada Vx=0; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_2= 100;
float y_2=250;
float teta_2=100*tiempo;
//polea3
/*La polea 3 se arranca de la posición x=100 y=450
Se traslada Vx=200; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_3= 100 + 200*tiempo;
float y_3=450;
float teta_3=100*tiempo;
/*
Rueda rotando alrededor de eje que pasa por
su centro de masa
*/
float teta_rueda=200*tiempo;
ruedas[0].mover(teta_rueda);
/*
La regla oscila armónicamente con frecuencia
igual a 2 Hz y amplitud 0.2 rad
y fase inicial cero
*/
float frecuencia= 2;
float teta_regla_radianes=(float)
(0.2*(Math.sin(2*Math.PI*frecuencia*tiempo)));
float teta_regla_grados= (float)
(Math.toDegrees(teta_regla_radianes));
cuerposRect[1].rotar(700,320,teta_regla_grados);
//actualizar escena
pizarra.setEstadoEscena(poleas, ruedas, cuerposRect);
}//fin Hilo
17
/*Hilo responsable de la animación
El trabajo de animación es mejor manejarlo en hilo
para evitar bloqueos de la aplicación
debido al manejo simultáneo de la GUI con la Acivity
*/
private HiloAnimacion hilo;
//administrador de diseño
LinearLayout linear_principal = new LinearLayout(this);
linear_principal.setOrientation(LinearLayout.VERTICAL);
linear_principal.setGravity(Gravity.CENTER_HORIZONTAL);
linear_principal.setGravity(Gravity.FILL);
linear_principal.setBackgroundColor(Color.rgb(250, 150, 50));
18
/*pegar el objeto tipo PizarraDibujo)*/
//parámetro de pegada
LinearLayout.LayoutParams parametrosPegada= new
LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_P
ARENT,0);
parametrosPegada.setMargins(50, 50, 50, 50);
parametrosPegada.weight = 1.0f;
//pegar
linear_principal.addView(pizarra, parametrosPegada);
return linear_principal;
//trea poleas
//polea ubicada inicialmente en (10,10) y de radio 50
polea_1=new Polea(100,100,50);
poleas[0]=polea_1;
}
}
19
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.curso_simulaciones.minovenaapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity
android:name="com.curso_simulaciones.minovenaapp.controlador.Activida
dPrincipalMiNovenaApp"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Figura 3
Este método para esta clase dibujará un círculo sencillo con la letra R en su interior.
canvas.save();
//rotar
canvas.rotate(posicionAngularRotacionEjeXY,posicionEjeRotacionX,posic
ionEjeRotacionY);
//regresar la rotación
canvas.restore();
}
Las clases Polea, CuerpoRectangular y Rueda que heredan de CuerpoRigido tendrán
este método, el cual heredarán también, pero con el mismo código que tenían en
MiNovenaApp. Esto significa que, aunque en este caso están heredando el método de
sobreescritura de método.
MI DECIMA APP
21
Crear un proyecto denominado MiDecimaApp con la misma estructura de MiNovenaApp,
ActividadPrincipalMiDecimaApp).
Figura 4
Los códigos de las clases Polea, CuerpoRectangular y Rueda siguen iguales a los de
MiNovenaApp: agregarlos. Los códigos de la clase CuerpoRigido, Pizarra e HiloAnimacion
tienen algunos cambios (marcadosen amarillo). Estos códigos son los siguientes
(agregarlos).
Clase CuerpoRigido
/**
* Constructor por defecto del cuerpo rígido.
* Su centro de masa está ubicado en la
* posición (0,0). La posición angular es cero
* y su color es rojo
*/
public CuerpoRigido() {
22
}
/**
* Constructor de CuerpoRigido
* cuyo centro de masa está
* ubicado en (posicionInicialX,posicionInicialX)
*/
/**
* Modifica el color del cuerpo rígido
*
* @param color
*/
public void setColor(int color) {
this.color = color;
}
/**
* Devuelve el color del cuerpo rígido
*
* @return
*/
public int getColor() {
return color;
}
/*
Se podría hacer un método setPosicion(x,y)
para cambiar la posición del centro de masa, pero más adelante
esta el método mover(x,y) que hace esto
*/
/**
* Retorna la posicion en X
* del centro de masa
*
* @return
*/
public float getPosicionX() {
return posicionCentroMasaX;
}
/**
* Retorna posicion en Y
* del centro de masa
*
* @return
*/
public float getPosicionY() {
23
return posicionCentroMasaY;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido
*
* @param posicionCentroMasaX
* @param posicionCentroMasaY
*/
public void mover(float posicionCentroMasaX, float
posicionCentroMasaY) {
this.posicionCentroMasaX = posicionCentroMasaX;
this.posicionCentroMasaY = posicionCentroMasaY;
/**
* Modifica la posición angular del cuerpo rígido
* alrededor de une eje uqe pasa por su centro
* de masa
*
* @param posicionAngular
*/
public void mover(float posicionAngular) {
// this.posicionAngularRotacionCentroMasa = posicionAngular;
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido y genera una rotación
* alrededor del eje que pasa por éste
* @param posicionCentroMasaX
* @param posicionCentroMasaY
* @param posicionAngular
*/
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Genera rotación del cuerpo rígido a la
* posición angular posicionAngularRotacionEjeXY
* alrededor de eje que pasa por
* (posicionEjeRotacionX,posicionEjeRotacionY)
* @param posicionEjeRotacionX 24
* @param posicionEjeRotacionY
* @param posicionAngular
*/
this.posicionEjeRotacionX=posicionEjeRotacionX;
this.posicionEjeRotacionY=posicionEjeRotacionY;
this.posicionAngularRotacionEjeXY=posicionAngular;
canvas.save();
//rotar
canvas.rotate(posicionAngularRotacionEjeXY,posicionEjeRotacionX,posic
ionEjeRotacionY);
//regresar la rotación
canvas.restore();
/**
* Constructor
*
* @param context
*/
public Pizarra(Context context) {
super(context); 25
}
this.cuerpos = cuerpos;
if (cuerpos != null)
dibujarEscena(canvas, pincel);
}
Código de HiloAnimacion
26
public class HiloAnimacion extends Thread{
/*
Este método construtor para un hilo que
maneja la animación de la pizarra
*/
public HiloAnimacion(Pizarra pizarra, CuerpoRigido[] cuerpos ){
this.pizarra=pizarra;
this.cuerpos=cuerpos;
}
@Override
public void run(){
corriendo = true;
while (corriendo==true){
try {
Thread.sleep(periodo_muestreo);//esto en milisegundos
} catch (InterruptedException e) {
e.printStackTrace();
}
//estaba a 0.1 f
tiempo=tiempo+0.01f;
//cambio de estado de la escena física en la pizarra
cambiarEstadosEscenaPizarra(tiempo);
/*
Rota el rígido sencillo alrededor de su centro de masa
*/
float teta_rigido=200*tiempo;
//mover las poleas
cuerpos[0].mover(teta_rigido);
//polea_1
/*La polea 1 arranca de la posición x=100 y=100 27
Se traslada con velocidad constante en x Vx=200; Vy=0;
No rota alrededor de su eje, W=0
*/
float x_1= 100 + 200*tiempo;
float y_1=100;
//polea_2
/*La polea 2 se arranca de la posición x=100 y=250
No se traslada Vx=0; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_2= 100;
float y_2=250;
float teta_2=100*tiempo;
//polea3
/*La polea 3 se arranca de la posición x=100 y=450
Se traslada Vx=200; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_3= 100 + 200*tiempo;
float y_3=450;
float teta_3=100*tiempo;
/*
Rueda rotando alrededor de eje que pasa por
su centro de masa
*/
float teta_rueda=200*tiempo;
cuerpos[4].mover(teta_rueda);
/*
La regla oscila armónicamente con frecuencia
igual a 2 Hz y amplitud 0.2 rad
y fase inicial cero
*/
float frecuencia= 2;
float teta_regla_radianes=(float)
(0.2*(Math.sin(2*Math.PI*frecuencia*tiempo)));
float teta_regla_grados= (float)
(Math.toDegrees(teta_regla_radianes));
cuerpos[6].rotar(700,320,teta_regla_grados);
//actualizar escena
pizarra.setEstadoEscena(cuerpos);
}//fin Hilo
28
Agregar los códigos de las clases Polea, CuerpoRectangular y Rueda. Sonlos mimsode
MiNovenaApp.
Código de ActividadPrincipalMiDecimaApp
//administrador de diseño
LinearLayout linear_principal = new LinearLayout(this);
linear_principal.setOrientation(LinearLayout.VERTICAL);
linear_principal.setGravity(Gravity.CENTER_HORIZONTAL);
linear_principal.setGravity(Gravity.FILL);
linear_principal.setBackgroundColor(Color.rgb(250, 150, 50));
return linear_principal;
}
//trea poleas
//polea ubicada inicialmente en (10,10) y de radio 50
polea_1=new Polea(100,100,50); 30
cuerpos[1]=polea_1;
}
}
Declarar la actividad principal en el archivo manifiesto (exigir que la pantalla quede siempre
sobrescritura de método.
31
Figura 5
Un método sin implementar se deb declarar abstracto. Sólo está el nombre de éste y sin
//Método abstracto
public abstract void dibujese(Canvas canvas, Paint pincel) ;
Una clase que al menos tenga un método abstracto se debe declarar también abstracta. Por
abstracta.
public abstract class CuerpoRigido {
abstractas se les llama resúmenes. Una clase abstracta para Java es una clase de la que
nunca se van a crear instancias: simplemente va a servir como superclase a otras clases. No
Una clase abstracta tiene como intención única la de unificar atributos y métodos de las
A su vez, las clases abstractas contienen métodos abstractos: la situación es la misma. Para
Sólo puede existir dentro de una clase abstracta. De esta forma se evita que haya
métodos que no se puedan ejecutar dentro de clases concretas. Visto de otra manera,
si una clase incluye un método abstracto, forzosamente la clase será una clase
abstracta.
un método no ejecutable, lo que la obliga a ser una subclase abstracta. Para que la
subclase sea concreta habrá de implementar métodos sobre-escritos para todos los
33
Un método abstracto para Java es un método que nunca va a ser ejecutado porque no tiene
¿Qué utilidad tiene un método abstracto? Se puede ver un método abstracto como una
palanca que tiene dos efectos: el primero, que no se puedan crear objetos de una clase. El
segundo, que todas las subclases sobre-escriban el método declarado como abstracto.
Que un método sea abstracto tiene otra implicación adicional: que se pueda invocar el
método abstracto sobre una variable de la superclase que apunta a un objeto de una
subclase de modo que el método que se ejecute sea el correspondiente al tipo dinámico de
la variable. En cierta manera, podría verse como un método sobre-escrito para que Java
comprenda que debe buscar dinámicamente el método adecuado según la subclase a la que
apunte la variable.
¿Es necesario que una clase que tiene uno o más métodos abstractos se defina como
como abstracta porque si no se hace así se tendría un método de una clase concreta no
una clase puede ser declarada como abstracta y no contener métodos abstractos. En
algunos casos la clase abstracta simplemente sirve para efectuar operaciones comunes a
¿Una clase que hereda de una clase abstracta puede ser no abstracta? Sí, de hecho,
esta es una de las razones de ser de las clases abstractas. Una clase abstracta no puede
ser instanciada, pero pueden crearse subclases concretas sobre la base de una clase
abstracta, y crear instancias de estas subclases. Para ello hay que heredar de la clase
estryctura de las apps que se han ido desarrollando en este módulo, Figura 6 (la actividad
34
Figura 6
(agregarlo)
/**
* Constructor por defecto del cuerpo rígido.
* Su centro de masa está ubicado en la
* posición (0,0). La posición angular es cero
* y su color es rojo
*/
public CuerpoRigido() {
}
/**
* Constructor de CuerpoRigido
* cuyo centro de masa está
* ubicado en (posicionInicialX,posicionInicialX)
*/
35
/**
* Modifica el color del cuerpo rígido
*
* @param color
*/
public void setColor(int color) {
this.color = color;
}
/**
* Devuelve el color del cuerpo rígido
*
* @return
*/
public int getColor() {
return color;
}
/*
Se podría hacer un método setPosicion(x,y)
para cambiar la posición del centro de masa, pero más adelante
esta el método mover(x,y) que hace esto
*/
/**
* Retorna la posicion en X
* del centro de masa
*
* @return
*/
return posicionCentroMasaX;
}
/**
* Retorna posicion en Y
* del centro de masa
*
* @return
*/
public float getPosicionY() {
return posicionCentroMasaY;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido
*
* @param posicionCentroMasaX
* @param posicionCentroMasaY
*/
public void mover(float posicionCentroMasaX, float
posicionCentroMasaY) {
this.posicionCentroMasaX = posicionCentroMasaX;
this.posicionCentroMasaY = posicionCentroMasaY; 36
}
/**
* Modifica la posición angular del cuerpo rígido
* alrededor de une eje uqe pasa por su centro
* de masa
*
* @param posicionAngular
*/
public void mover(float posicionAngular) {
// this.posicionAngularRotacionCentroMasa = posicionAngular;
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido y genera una rotación
* alrededor del eje que pasa por éste
* @param posicionCentroMasaX
* @param posicionCentroMasaY
* @param posicionAngular
*/
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Genera rotación del cuerpo rígido a la
* posición angular posicionAngularRotacionEjeXY
* alrededor de eje que pasa por
* (posicionEjeRotacionX,posicionEjeRotacionY)
* @param posicionEjeRotacionX
* @param posicionEjeRotacionY
* @param posicionAngular
*/
this.posicionEjeRotacionX=posicionEjeRotacionX;
this.posicionEjeRotacionY=posicionEjeRotacionY;
this.posicionAngularRotacionEjeXY=posicionAngular;
//Método abstracto 37
public abstract void dibujese(Canvas canvas, Paint pincel) ;
Los códigos de Polea, CuerpoRectangular y Rueda son los mismos de las dos apps que se
han desarrolllado en este módulo. Agregarlo. Estas clases heredan de la clase abstracta
Los códigos de las otras clases ya no instancian la clase CuerpoRigido. Los códigos son
/*
Este método construtor para un hilo que
maneja la animación de la pizarra
*/
public HiloAnimacion(Pizarra pizarra, CuerpoRigido[] cuerpos ){
this.pizarra=pizarra;
this.cuerpos=cuerpos;
}
@Override
public void run(){
corriendo = true;
while (corriendo==true){
try {
Thread.sleep(periodo_muestreo);//esto en milisegundos
} catch (InterruptedException e) { 38
e.printStackTrace();
}
//estaba a 0.1 f
tiempo=tiempo+0.01f;
//cambio de estado de la escena física en la pizarra
cambiarEstadosEscenaPizarra(tiempo);
//polea_1
/*La polea 1 arranca de la posición x=100 y=100
Se traslada con velocidad constante en x Vx=200; Vy=0;
No rota alrededor de su eje, W=0
*/
float x_1= 100 + 200*tiempo;
float y_1=100;
//polea_2
/*La polea 2 se arranca de la posición x=100 y=250
No se traslada Vx=0; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_2= 100;
float y_2=250;
float teta_2=100*tiempo;
//polea3
/*La polea 3 se arranca de la posición x=100 y=450
Se traslada Vx=200; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_3= 100 + 200*tiempo;
float y_3=450;
float teta_3=100*tiempo;
/*
Rueda rotando alrededor de eje que pasa por
su centro de masa
*/
float teta_rueda=200*tiempo;
cuerpos[3].mover(teta_rueda); 39
/*
La regla oscila armónicamente con frecuencia
igual a 2 Hz y amplitud 0.2 rad
y fase inicial cero
*/
float frecuencia= 2;
float teta_regla_radianes=(float)
(0.2*(Math.sin(2*Math.PI*frecuencia*tiempo)));
float teta_regla_grados= (float)
(Math.toDegrees(teta_regla_radianes));
cuerpos[5].rotar(700,320,teta_regla_grados);
//actualizar escena
pizarra.setEstadoEscena(cuerpos);
}//fin Hilo
//administrador de diseño
LinearLayout linear_principal = new LinearLayout(this);
linear_principal.setOrientation(LinearLayout.VERTICAL);
linear_principal.setGravity(Gravity.CENTER_HORIZONTAL);
linear_principal.setGravity(Gravity.FILL);
linear_principal.setBackgroundColor(Color.rgb(250, 150, 50));
/*pegar el objeto tipo PizarraDibujo)*/
//parámetro de pegada
LinearLayout.LayoutParams parametrosPegada= new
LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_P
ARENT,0);
parametrosPegada.setMargins(50, 50, 50, 50);
parametrosPegada.weight = 1.0f;
//pegar
linear_principal.addView(pizarra, parametrosPegada);
return linear_principal;
} 41
//trea poleas
//polea ubicada inicialmente en (10,10) y de radio 50
polea_1=new Polea(100,100,50);
cuerpos[0]=polea_1;
}
}
42
despliegue horizontal.
INTERFACE
Java no permite la denominada herencia múltiple, es decir una clase sólo puede derivarse
de una sola madre y no de varias. Para lograr algo parecido usa las denominadas
"interfaces". Éstas pueden verse simplemente como una forma, es como un molde,
adicionalmente miembros datos (los cuales podrán ser únicamente tipos básicos y serán
son implementadas por clases las cuales deben definir todos sus métodos. Una interfaz no
En resumen, una interface es una construcción similar a una clase abstracta en Java, pero
Por ejemplo,
poner abstract public porque por defecto todos los métodos son abstract
public. Por lo tanto, un interface en Java no implementa ninguno de los métodos que
de clase, públicos y constantes. No hace falta incluir las palabras public static
final porque todos los campos serán tratados como si llevaran estas palabras. 43
Recordar que static equivale a “de clase” y final a “constante”. Las interfaces
pueden ser un lugar interesante para declarar constantes que van a ser usadas por
Una clase puede “derivar” de una interface de la misma manera en que puede derivar de
otra clase. No obstante, se dice que la interface se implementa (implements), no se
Una clase puede implementar uno o varios interfaces en Java (se indica con
extender una clase. Implementar varios interfaces en una sola clase es lo más parecido
adicionales: resortes y flechas (para representar vectores). Para esto se diseñarán la clase
elegante a nivel de programación ni de lógica). Como los objetos de estas clases también
deben poderse dibujar deberán incluir el método dibujese( ) que se ha diseñado para
que se puedan dibujar los objetos de laboratorio en objetos de la clase Pizarra. Para esto
lo mejor será diseñar una interface que se denominará Dibujable que posee el método
dibujese() sin implementar, la cual (la interface) la implementarán todos las clases cuyos
implementará la interface Dibujable y por lo tanto todas sus hijas que pretendan no
implementa ese método por lo tanto debe ser también una clase abstracta (no se pueden
hacer objetos con ella). Esta clase tiene las hijas Polea, CuerpoRectangular y Rueda
44
Figura 7
objetos_laboratorio aparece la interface Dibujable. Esta se crea como las clases, pero
45
Figura 8
Figura 9
/**
* método que deben implementar las clases cuyos objetos
* serán dibujables en Pizarra que herede de View.
* @param canvas
* @param pincel
*/
public void dibujese(Canvas canvas, Paint pincel);
/**
* Método para que se dibujen los objetos Dibujables,
* es decir, los objetos que implementanla interface Dibujable
* @param canvas
* @param pincel
*/
public abstract void dibujese(Canvas canvas, Paint pincel);
/**
* Constructor por defecto del cuerpo rígido.
* Su centro de masa está ubicado en la
* posición (0,0). La posición angular es cero
* y su color es rojo
*/
public CuerpoRigido() {
/**
* Constructor de CuerpoRigido
* cuyo centro de masa está
* ubicado en (posicionInicialX,posicionInicialX)
*/
/**
* Modifica el color del cuerpo rígido
*
* @param color 47
*/
public void setColor(int color) {
this.color = color;
}
/**
* Devuelve el color del cuerpo rígido
*
* @return
*/
public int getColor() {
return color;
}
/*
Se podría hacer un método setPosicion(x,y)
para cambiar la posición del centro de masa, pero más adelante
esta el método mover(x,y) que hace esto
*/
/**
* Retorna la posicion en X
* del centro de masa
*
* @return
*/
return posicionCentroMasaX;
}
/**
* Retorna posicion en Y
* del centro de masa
*
* @return
*/
public float getPosicionY() {
return posicionCentroMasaY;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido
*
* @param posicionCentroMasaX
* @param posicionCentroMasaY
*/
public void mover(float posicionCentroMasaX, float
posicionCentroMasaY) {
this.posicionCentroMasaX = posicionCentroMasaX;
this.posicionCentroMasaY = posicionCentroMasaY;
48
/**
* Modifica la posición angular del cuerpo rígido
* alrededor de une eje uqe pasa por su centro
* de masa
*
* @param posicionAngular
*/
public void mover(float posicionAngular) {
// this.posicionAngularRotacionCentroMasa = posicionAngular;
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Modifica la posición (posicionCentroMasaX,posicionCentroMasaY)
* del centro de masa del cuerpo rígido y genera una rotación
* alrededor del eje que pasa por éste
* @param posicionCentroMasaX
* @param posicionCentroMasaY
* @param posicionAngular
*/
this.posicionEjeRotacionX = posicionCentroMasaX;
this.posicionEjeRotacionY = posicionCentroMasaY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Genera rotación del cuerpo rígido a la
* posición angular posicionAngularRotacionEjeXY
* alrededor de eje que pasa por
* (posicionEjeRotacionX,posicionEjeRotacionY)
* @param posicionEjeRotacionX
* @param posicionEjeRotacionY
* @param posicionAngular
*/
this.posicionEjeRotacionX=posicionEjeRotacionX;
this.posicionEjeRotacionY=posicionEjeRotacionY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
49
/**
* Resorte de longitud 10f
* ancho 20f y horizontal y
* origen en (0,0)
*/
public Resorte() {
this.longitudNatural = 10f;
this.longitud = longitudNatural;
this.ancho = 20f;
}
/**
* Modifica la longitud del objeto de laboratorio Resorte
*
* @param longitud
*/
public void setLongitud(float longitud) {
this.longitud = longitud;
/**
* Devuelve la longitud del objeto de laboratorio Resorte
*
* @return longitud
*/
public float getLongitud() {
return longitud;
}
/**
* Modifica la longitud natural del objeto de laboratorio Resorte
*
* @param longitudNatural
*/ 50
public void setLongitudNatural(float longitudNatural) {
this.longitudNatural = longitudNatural;
this.longitud = longitudNatural;
/**
* Devuelve la longitud natural del objeto de laboratorio Resorte
*
* @return longitudNatural
*/
return longitudNatural;
}
/**
* Modifica la posicion del objeto de laboratorio
*
* @param posicionX
* @param posicionY
*/
this.posicionX = posicionX;
this.posicionY = posicionY;
/**
* Regresa la posición del laboratorio
*
* @return
*/
return coordenadas;
/**
* Modifica el grosor de la línea con la que se dibujará
*
* @param grosorLinea
*/ 51
public void setGrosorLinea(float grosorLinea) {
this.grosorLinea = grosorLinea;
/**
* Devuelve el grosor de la línea con la que se dibuja
*
* @return
*/
public float getGrosorLinea() {
return grosorLinea;
}
/**
* Modifica el color del objeto de laboratorio
*
* @param color
*/
this.color = color;
/**
* Devuelve el color del objeto de laboratorio
*
* @return
*/
public int getColor() {
return color;
}
/**
* Modifica el ancho del objeto de laboratorio Resorte2D
*
* @param ancho
*/
public void setAncho(float ancho) {
this.ancho = ancho;
/**
* Devuelve el ancho del objeto de laboratorio Resorte2D
*
* @return
*/
52
public float getAncho() {
return ancho;
}
/**
* Genera rotación del resorte a la
* posición angular posicionAngular
* alrededor de eje que pasa por
* (posicionX,posicionY)
* @param posicionAngular
*/
this.posicionAngular=posicionAngular;
pincel.setStrokeWidth(grosorLinea);
pincel.setColor(color);
pincel.setStyle(Paint.Style.STROKE);
//restaurar pincel 53
pincel.setStrokeWidth(grosorInicialLinea);
pincel.setStyle(Paint.Style.FILL);
//restaurar el canvas
canvas.restore();
/**
* Constructor por defecto
* Fecha con origen en (0,0),
* longitud 20f, horizontal y
* sentido + X
*/
public Flecha() {
this.posicionX = 0;
this.posicionY = 0;
this.longitud = 20f;
/**
* Modifica la longitud del objeto de laboratorio Flecha
*
* @param longitud
*/
this.longitud = longitud;
}
return longitud;
}
54
/**
* Modifica la posicion del objeto de laboratorio
* @param posicionX
* @param posicionY
*/
this.posicionX=posicionX;
this.posicionY=posicionY;
/**
* Regresa la posición del laboratorio
* @return
*/
coordenadas[0]=posicionX;
coordenadas[1]=posicionY;
return coordenadas;
/**
* Modifica el grosor de la línea con la que se dibujará
* @param grosorLinea
*/
this.grosorLinea=grosorLinea;
}
/**
* Devuelve el grosor de la línea con la que se dibuja
* @return
*/
public float getGrosorLinea(){
return grosorLinea;
}
/**
* Modifica el color del objeto de laboratorio
* @param color
*/
55
public void setColor(int color){
this.color=color;
/**
* Devuelve el color del objeto de laboratorio
* @return
*/
public int getColor(){
return color;
}
/**
* Genera rotación de la flecha a la
* posición angular posicionAngular
* alrededor de eje que pasa por
* (posicionX,posicionY)
* @param posicionAngular
*/
this.posicionAngular=posicionAngular;
pincel.setStrokeWidth(grosorLinea);
pincel.setColor(color);
//restaurar pincel
pincel.setStrokeWidth(grosorInicialLinea);
pincel.setStyle(Paint.Style.FILL);
//restaurar el canvas
canvas.restore();
}
}
El código de las clases Polea, CuerpoRectangular y Rueda sigue siendo igual al de las
/**
* Constructor
*
* @param context
*/
public Pizarra(Context context) {
super(context);
}
this.objetosLab = cuerpos;
if (objetosLab != null)
dibujarEscena(canvas, pincel);
/*
Este método construtor para un hilo que
maneja la animación de la pizarra
*/
public HiloAnimacion(Pizarra pizarra, ObjetoLaboratorio[] cuerpos
){
this.pizarra=pizarra; 58
this.objetosLab=cuerpos;
}
@Override
public void run(){
corriendo = true;
while (corriendo==true){
try {
Thread.sleep(periodo_muestreo);//esto en milisegundos
} catch (InterruptedException e) {
e.printStackTrace();
}
//estaba a 0.1 f
tiempo=tiempo+0.01f;
//cambio de estado de la escena física en la pizarra
cambiarEstadosEscenaPizarra(tiempo);
//polea_1
/*La polea 1 arranca de la posición x=100 y=100
Se traslada con velocidad constante en x Vx=200; Vy=0;
No rota alrededor de su eje, W=0
*/
float x_1= 100 + 200*tiempo;
float y_1=100;
//polea_2
/*La polea 2 se arranca de la posición x=100 y=250
No se traslada Vx=0; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_2= 100;
float y_2=250;
float teta_2=100*tiempo;
//polea3
/*La polea 3 se arranca de la posición x=100 y=450
Se traslada Vx=200; Vy=0;
Rota alrededor de su eje, W=100
*/
float x_3= 100 + 200*tiempo;
float y_3=450;
float teta_3=100*tiempo; 59
/*
Rueda rotando alrededor de eje que pasa por
su centro de masa
*/
float teta_rueda=200*tiempo;
((CuerpoRigido)objetosLab[3]).mover(teta_rueda);//casting
/*
La regla oscila armónicamente con frecuencia
igual a 2 Hz y amplitud 0.2 rad
y fase inicial cero
*/
float frecuencia= 2;
float teta_regla_radianes=(float)
(0.2*(Math.sin(2*Math.PI*frecuencia*tiempo)));
float teta_regla_grados= (float)
(Math.toDegrees(teta_regla_radianes));
((CuerpoRigido)objetosLab[5]).rotar(700,320,teta_regla_grados);//cast
ing
((Resorte)objetosLab[8]).setLongitud(longitudNatural+y_resorte_1);//c
asting
//actualizar escena
pizarra.setEstadoEscena(objetosLab);
}
(agregarlo).
60
//administrador de diseño
LinearLayout linear_principal = new LinearLayout(this);
linear_principal.setOrientation(LinearLayout.VERTICAL);
linear_principal.setGravity(Gravity.CENTER_HORIZONTAL);
linear_principal.setGravity(Gravity.FILL);
linear_principal.setBackgroundColor(Color.rgb(250, 150, 50));
return linear_principal;
//trea poleas
//polea ubicada inicialmente en (10,10) y de radio 50
polea_1=new Polea(100,100,50);
objetoLab[0]=polea_1;
//resorte_1
resorte_1=new Resorte();
resorte_1.setLongitudNatural(300);
resorte_1.setPosicion(100,100);
resorte_1.setColor(Color.BLUE);
resorte_1.rotar(90);
objetoLab[8]=resorte_1;
}
}
Figura 10
TALLER
1. Estudiar con el debido detalle las aplicaciones expuestas en este módulo (ESTO ES
Figura 11.
Figura 11
Los requisitos son similares a los de la app MiDecimoSegundaApp y son los siguientes
capacidad a las clases que la implementen que sus objetos se puiedan dibujar en un
this.m=m;
objetos:
colores.
Tabla 1
Clase Caricatura
Estrella Fija
Marciano
Selenita
Venusiano
Ayuda:
Un posible código para la clase Extraterrestre (se puede usar para la tarea) es el
siguiente:
/**
* Constructor por defecto del extraterrestre.
* Su "centroide" está ubicado en la
* posición (0,0). La posición angular es cero
* y su color es rojo
*/
public Extraterrestre() {
}
67
/**
* Constructor de CuerpoRigido
* cuyo "centroide" está
* ubicado en (posicionCentroideX,posicionCentroideY)
*/
/**
* Modifica el color del extraterrestre
*
* @param color
*/
public void setColor(int color) {
this.color = color;
}
/**
* Devuelve el color del extraterrestre
*
* @return
*/
public int getColor() {
return color;
}
/**
* Retorna la posicion en X
* del "centroide" del extraterrestre
*
* @return
*/
return posicionCentroideX;
}
/**
* Retorna posicion en Y
* del "centroide" del extraterrestre
*
* @return
*/
public float getPosicionY() {
return posicionCentroideY;
}
/** 68
* Modifica la posición (posicionCentroideX,posicionCentroideY)
* del "centroide" del extraterrestre
*
* @param posicionCentroideX
* @param posicionCentroideY
*/
public void mover(float posicionCentroideX, float
posicionCentroideY) {
this.posicionCentroideX = posicionCentroideX;
this.posicionCentroideY = posicionCentroideY;
/**
* Modifica la posición angular del extraterrestre
* alrededor de une eje que pasa por su "centroide"
*
*
* @param posicionAngular
*/
public void mover(float posicionAngular) {
// this.posicionAngularRotacionCentroMasa = posicionAngular;
this.posicionEjeRotacionX = posicionCentroideX;
this.posicionEjeRotacionY = posicionCentroideY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
/**
* Modifica la posición (posicionCentroide,posicionCentroideY)
* del "centroide" del extraterrestre y genera una rotación
* alrededor del eje que pasa por éste
* @param posicionCentroideX
* @param posicionCentroideY
* @param posicionAngular
*/
this.posicionEjeRotacionX = posicionCentroideX;
this.posicionEjeRotacionY = posicionCentroideY;
this.posicionAngularRotacionEjeXY=posicionAngular;
}
Un posible código para la clase Marciano (se puede usar para la tarea) es el siguiente:
/**
* Constructor por defecto
* del marciano con "centroide" en (0,0)
* y de radio 50f
*/
public Marciano() {
super();
/**
* Constructor del marciano con "centroide"
* en (posicionCentroideX,posicionCentroideY)
* y diámetro igual a 2*radio
*/
canvas.save();
//magnificar
canvas.scale(m,m,posicionCentroideX,posicionCentroideY);
//rotar
canvas.rotate(posicionAngularRotacionEjeXY,posicionEjeRotacionX,posici
onEjeRotacionY);
//dibujar círculo de la cara del marciano
float radio=50f;
pincel.setStyle(Paint.Style.FILL);
canvas.drawCircle(posicionCentroideX, posicionCentroideY,
radio, pincel);
pincel.setColor(Color.BLACK);
//dibujar circunferencia de la cara del marciano
pincel.setStyle(Paint.Style.STROKE);
canvas.drawCircle(posicionCentroideX, posicionCentroideY,
radio, pincel);
canvas.drawRect(xs_izquierda,ys_izquierda,xi_derecha,yi_derecha,pincel
);
pincel.setColor(color);
pincel.setStrokeWidth(20f);
canvas.drawLine(x_i_oreja_derecha,y_i_oreja_derecha,x_s_oreja_derecha,
y_s_oreja_derecha,pincel);
canvas.drawLine(x_i_oreja_izquierda,y_i_oreja_izquierda,x_s_oreja_izqu
ierda,y_s_oreja_izquierda,pincel);
71
//regresa la rotación
canvas.restore();
Un código inicial para la clase HiloAnimación (se puede usar para la tarea) es el
siguiente:
/*
Este método construtor para un hilo que
maneja la animación de la pizarra
*/
public HiloAnimacion(Pizarra pizarra, ObjetoEspacial[] cuerpos) {
this.pizarra = pizarra;
this.objetosEspacio = cuerpos;
}
@Override
public void run() {
corriendo = true;
//estaba a 0.1 f
tiempo = tiempo + 0.01f;
//cambio de estado de la escena física en la pizarra
cambiarEstadosEscenaPizarra(tiempo);
72
}
//mover marciano
((Extraterrestre)
objetosEspacio[0]).mover(posicion_marciano_x,
posicion_marciano_y);//casting
objetosEspacio[0].setMagnificarCaricatura(1 + 0.2f * tiempo);
((Extraterrestre)
objetosEspacio[0]).mover(teta_grados);//casting
//cambiar color
if(posicion_marciano_x>600){
((Extraterrestre)objetosEspacio[0]).setColor(Color.GREEN);//casting
}
//actualizar escena
pizarra.setEstadoEscena(objetosEspacio);
73
REFERENCIAS