JBoss SSO – tune in development
Marzo 31, 2008
Pasos armados a partir de la wiki http://labs.jboss.com/wiki?windowstate=maximized
pero con los fuentes del proyecto y no con la distribucion binaria.. ademas no usamos el CR1 sino que el trunk. Para usar el CR1 cambiamos el repositorio a http://anonsvn.jboss.org/repos/jboss-sso/dev/tags/jboss-sso-1.0CR1/
Primero :
svn co http://anonsvn.jboss.org/repos/jboss-sso/dev/trunk/
Luego:
vi local.properties
y modificamos lo siguiente:
deploy.dir=default
jboss.home=/home/<user>/<jboss-4.2.2.GA>
Luego debemos tener instalado ant.. y todas sus librerias en /usr/share/ant/lib/
sino bajamos http://www.apache.org/dist/ant/binaries/apache-ant-1.7.0-bin.zip y copiamos todo el directorio lib a /usr/share/ant/lib/ y listo.
Tenemos que revisar que no tengamos una variable de entorno llamada JBOSS_HOME que apunte a otro jboss que no sea el que estamos usando
Con esto hecho ya podemos hacer..
en el directorio <jboss-sso>/components/build/
ant installSSO
Luego en el directorio ../jboss_federation_server/
ant deploy-exploded
y ahora debemos meternos con las configuraciones de red:
editamos el archivo /etc/hosts
nos deberia quedar algo asi
127.0.0.1 localhost node1.jboss.com
127.0.1.1 salaboy-desktop node1.jboss.org
127.0.2.1 node2.jboss.com
Una vez que tenemos esto.. debemos activar el ssl en el tomcat de jboss y generar un keystore local para que se use en la comunicacion ssl.
vamos a /home/salaboy/programas/jboss-4.2.2.GA/server/default/deploy/jboss-web.deployer/
y editamos el archivo server.xml
Descomentamos
<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
maxThreads=”150″ scheme=”https” secure=”true”
clientAuth=”false” sslProtocol=”TLS” />
y agregamos la siguiente propiedad:
keystorePass=”<password>”
Las <password> que pongamos aca debera ser la misma usada al generar el keystore.
para generar el keystore vamos a nuestro home y hacemos lo siguiente:
salaboy@salaboy-desktop:~$ keytool -genkey -keyalg “RSA” -keystore keystore
Enter keystore password: jboss-sso
What is your first and last name?
[Unknown]: jboss
What is the name of your organizational unit?
[Unknown]: jboss
What is the name of your organization?
[Unknown]: jboss
What is the name of your City or Locality?
[Unknown]: baires
What is the name of your State or Province?
[Unknown]: capfed
What is the two-letter country code for this unit?
[Unknown]: AR
Is CN=jboss, OU=jboss, O=jboss, L=baires, ST=capfed, C=AR correct?
[no]: yes
Enter key password for <mykey>
(RETURN if same as keystore password):
Como podemos ver esto nos deja generado un archivo llamado keystore en nuestro home..
al que debemos renombrar a .keystore para ser encontrado por las configuraciones por defecto de “tomcat”. si queremos cambiar de nombre o de lugar este archivo de keystore debemos especificarlo en una propiedad del sever.xml llamada keystoreFile="<path al keysotre>"
Y ahora si.. ya podemos correr un jboss con:
./run.sh -c default -b node1.jboss.com
Y deberiamos copiar el default y correr otro similar bindeado a node1.jboss.org
y probar que funcione el ejemplo situado en http://node1.jboss.org:8080/test
SCJP – Capitulo 3: Asignaciones (Parte #1)
Marzo 31, 2008
Stack y Heap
Entender los conceptos basicos de Stack y Heap hace mas facil entender temas como paso de argumentos, polimorfismo, hilos, exceptions, y garbage collection. Los metodos, variables, y objetos viven en 2 partes de la memoria, el Stack y el Heap. Por ahora nos vamos a preocupar solo en 3 tipos de cosas> variables de instancia, variables locales y objetos:
- Variables de instancia y objetos viven en el Heap
- Variables locales viven en el Stack
(Copiar figura pagina 175)
Literales, asignaciones y variables:
- Valores literales para todos los tipos de primitivos:
- Literales Enteros:
Hay 3 formas de representar numeros enteros en Java: decimal (base 10), octal (base
y hexadecimal (base 16)
- Decimal: int lenght=342;
- Octal: solo de 0 a 7 y anteponemos un 0: int nueve=011; podemos tener 21 digitos sin contar el 0
- Hex: no es case-sensitive! 0 a F, lo indicamos con 0x: int z=0xDEADCAFE;
Los literales enteros son definidos como int por defecto pero pueden ser especificados como long agregando una L al final: long so=0xFFFFL -> la L tampoco es case-sensitive y puede ser “l” ojo que confunde con el 1 (uno)
- Literales de punto flotante:
Son definidos como un numero, el simbolo de decimal y mas numeros representando la fraccion:
double d=111.3245;
Estos son definidos por defecto como doubles (64 bits), pero si queremos asignar un literal de punto flotante a una variable de tipo float(32 bits) debemos agregar el sufijo F al final. EJ:
float f=23.4543; // Mal perdida de presicion!!!
float f=23.4543F; // Todo OK!Ojo si vemos literales con coma ej: int x=2,321; no compila por la coma! - Literales Booleanos:
Son true o false, nada mas. boolean f=0; // Error! ; int x=1; if (x) -> no compila no es como C - Literales caracter:
Son representado como un solo caracter entre comillas simples: char a=’a';
Tambien podemos poner valores unicode con el prefijo \u. ej: char n=’\u004E’;
Recordemos que los caracteres son solo enteros sin signo de 16 bits po lo cual podemos asignar cualquier valor numerico que este en el rago de 0 a 65535. char a=0×892; char c=(char) 70000 -> esta fuera de rango por eso hay que castear.
Tambien podemos representar los caracteres que no se pueden tipear como por ejemplo: linefeed, new line, horizontal tab, backspace y comillas simples. Ej: char a=’\”‘; para las comillas dobles o char n=’\n’; para new line. - Valores literales para Strings:
Son las representacion de un valor como un objeto string: String s=”hola mundo!”;
- Literales Enteros:
Operadores de Asignacion:
Es bastante sencillo con el operador igual (=) y asignamos el valor de la izquiera a la variable en la derecha. x=6; Las variables son solo contenedores de bits, con un tipo designado. Dentro de este contenedor tenemos un conjunto de bits que representan un valor. Por ejemplo, si tenemos un byte con valor 6, significa que tenemos el patron binario 00000110 dentro del contenedor de tipo byte. Pero que pasa cuando tenemos un contenedor de tipo Objeto?
Button b=new Button();
Que hay dentro del contenedor de tipo Button? esta el objeto Button? NO!!!! es solamente una variable de referencia. Y una variable de referencia contiene los bits que representan la manera de llevar a un objeto.
Asignacion de primitivas:
Podemos asignar a una variable primitiva un literal o el resultado de una expresio. Ej: int x=7; int y=x+2; int z=x*y; Que pasa si estamos tratando de asginar una variable byte? despues de todo un contenedor de tamanio byte no puede contener tantos bits como un contener int. Aca es donde se vuelve extranio!! Lo siguiente es legal: byte b=27; -> esto se puede porque se hace un casteo automatico.
Sabemos que un literal entero siempre es un int, pero mas importante es que el resultado de una expresion que incluye cualquier cosa con tamanio entero o menor, siempre es un int!!! (es decir, que si sumamos 2 bytes obtenemos un int) Entonces si hacemos byte c=a+b; y a y b son bytes, el codigo no compila, porque el resultado es un int, y si realmente necesitamos que sea un byte el resultado, debemos castearlo con c=(byte)a+b;
Casteo de primitivas:
Nos permite convertir de un tipo a otro. Cuando pasamos un valor grande a un contenedor pequenio se llama narrowing y requiere un cast explicito, donde nosotros le decimos al compilador que sabemos lo que estamos haciendo y que nos hacemos cargo por la conversion.
Si el valor es mas grande que el contenedor al que estamos casteando, no tenemos un error de runtime, sino que se toman los bits de la drecha que entren y los demas se descartan. Y si el bit de mas a la izquiera es un 1 entonces el valor sera negativo. (ya que es signed)
Es a proposito no?
Marzo 30, 2008
Con el siguiente comando creamos un backup de la base de datos especificada en el archivo especificado en la line.
/usr/bin/pg_dump -i -h <host> -p <port> -U <user> -F c -b -D -v -f “<filename>.backup” “<database>”
How To PHP + APACHE + MySQL = WebPage
Marzo 16, 2008
Vamos a ver como levantar una pagina web que utiliza una base de datos en MySQL y Utiliza el lenguaje de scripting PHP para generar paginas dinamicas. Todo esto en Window$ XP con la ayuda de EasyPHP.
Comenzamos bajando EasyPhp de la pagina oficial EasyPhp.org
Una vez que bajamos EasyPhp lo instalamos y luego dirigimos nuestro navegador hacia:
http://localhost/mysql/ Notar la ultima barra.. totalmente importante!
Para ir directamente al administrador de MySQL y crear la base de datos que utilizara nuestra pagina.
http://salaboy.files.wordpress.com/2008/03/phpmyadmin.jpg
En este caso levantaremos un backup de una base de datos ya creada, por esto accedemos al icono de SQL en el menu de la izquierda.
Buscamos el archivo .sql que queremos restaurar y le damos al boton continuar.
Una vez hecho esto ya tenemos la base de datos creada. Ahora lo unico que falta es crear un usuario que luego usaremos en Php para acceder a la misma.
Para esto vamos Home (icono en el menu de la izquierda) , luego en la pantalla principal vamos a base de datos.
Escogemos la base de datos MySQL y luego en el menu izquiero elegimos la tabla User. Una vez ahi en la pantalla principal hacemos click en la solapa de insertar y completamos con los datos del usuario y los permisos como se muestra en la siguiente pantalla. En este caso el usuario y la contrasenia son “tkd” y no estamos utilizando ninguna funcion para encriptar la contrasenia.
Con esto ya tenemos la base de datos y el usuario para acceder desde una aplicacion Web a la base de datos.
Lo unico que falta por aclarar es que nuestra pagina web debera ubicarse en el directorio www dentro de la carpeta de instalacion de EasyPhP, esto no es obligatorio pero si es la configuracion por defecto. Luego para acceder a cualquier pagina que tengamos en el webroot (la carpeta www) tenemos que dirigir nuestro navegador a http://localhost/[nombre de la carpeta de la pagina web dentro de www]
SCJP – Capitulo 2: Orientacion a Objetos (Parte #2)
Marzo 16, 2008
Sobre escritura / Sobre carga:
Metodos sobre escritos:
Cada vez qeu una clase hereda de un metodo tenemos que la oportunidad de sobre escribirlo. Con esto logramos que su comportamiento sea especifico para esta clase.
Cuando sobre escribimos un metodo no podemos cambiarle el modificador de acceso por uno mas restrictivo.
Tambien como regla de oro, un metodo sobre escrito debe cumplir con el contrato (signature) de la super clase.
Las reglas generales de sobre escritura son las siguientes:
- La lista de argumentos tiene que ser exactamente igual.
- El return type debe ser igual o de un subtipo del declarado en la super clase.
- El modificador de acceso no debe ser mas restrictivo.
- Los metodos puede ser sobre escritos soslo si se heredaron de una super clase.
- Los mtodos sobre escritos pueden tirar cualquier excepcion unchecked (runtime ex) sin importar lo que el metodo de la super clase haya declarado.
- EL metodo no debe tirar nuevas exceptions checked que no hayan sido declaradas en el metodo de la super clase.
- No podemos sobre escribir metodos marcados con final, ni con static.
Invocando la version de la super clase de un metodo sobre escrito:
Probablemente en algunos casos, vamos a querer tomar prestado codigo del metodo de la super clase, para reutilizarlo en el actual metodo sobre escrito. Para esto usamos la palabra clave super, Que nos da la posibilidad de invocar el metodo de la super clase en el metodo sobre escrito y nos permite continuar agregando codigo una vez terminada la ejecucion del metodo invocado con super.
Metodos sobre cargados:
Nos permite usar el mismo nombre de un metodo en la misma clase pero con diferentes argumentos (y opcionalmente diferente return type). Por lo general cuando sobre cargamos un metodo lo hacemos para simplificarle la vida a los que van a llamar a este metodo.
Reglas de sobre carga:
- Debe cambiar la lista de argumentos
- Puede cambiar el return type
- Puede cambier el modificador de acceso
- Puede declarar nuevas u otras exceptions
- Puede ser sobrecargado en la misma clase o en una subclase
Luego se decide que version del metodo ejecutar comparando la lista de argumentos.
En caso de haber metodos sobre cargados en una relacion de clase y super clase en los argumentos, lo que cuenta es la variable de referencia a la hora de decidir que metodo invocar.
(EJ!!)
Polimorfismo en metodos sobrecargados y sobreescritos:
El polimorfismo no importa cuando un metodo es sobre cargado, entonces se puede decir que el polimorfismo no determina que version sobrecargada del metodo es llamada, sino que el polimorfismo entra en juego cuando se tiene que tomar la desicion sobre que metodo sobre escrito debe llamarse.
!Ojo con confundir sobre carga con sobre escritura!!!
Casteo de variables de referencia:
Ya vimos como es posible usar ambas referencias, una referencia generica y una mas especifica para un tipo en particular:
Animal a=new Dog();
Pero que pasa si queremos llamar sobre la variable de referencia a un metodo que solo posee el subtipo? Para esto debemos castear la variable de referencia:
Dog d=(Dog)a; -> Downcasting (explicito)
El upcasting es implicito:
Dog d=new Dog();
Animal a=d; -> Upcasting implicito, es opcional poner el casteo (Animal)
Una cosa importante mas, si Dog implementa a Pet, luego Beagle extiende a Dog, pero Beagle no hace la declaracion que implementa Pet, igualmente Beagle es Pet!
No hay que dejarse enganiar por codigo donde vemos que se implementa una interfaz, pero los metodos de la interfaz no son implementados en la clase. Antes de poder saber si el codigo es legal o no, debemos ver las declaraciones de la super clase, para saber si ya se ha hecho cargo de implementar los metodos de dicha interfaz.
Implementando una interfaz:
Cuando implementamos una interfaz estamos aceptando cumplir con un contrato, es decir, que proveemos implementaciones legales para cada uno de los metodos definidos en esta interfaz.
Pero el contrato que aceptamos solo garantiza que la clase va a tener los metodos de la interfaz, pero no se garantiza que esten correctamente implementados.
La clase que realiza una implementacion de una interfaz debe seguir las siguientes reglas:
- Proveer una implementacion concreta (no abstracta) de todos los metodos declarados en la interfaz.
- Seguir las reglas legales de sobre escritura
- Declarar las exceptions no checked en la implementacion de los metodos que esten definidas en la signature de la interfaz, o pueden ser subclases de las exceptions definidas.
- Mantener el mismo signature de los metodos de la interfaz y el mismo tipo o un subtipo del return type
2 Reglas mas generales:
- Una clase puede implementar mas de una interfaz
- Una interfaz puede extend otra interfaz (tambien puede extender mas de una interfaz!! re loco!)
Return types Legales:
Vamos a ver que podemos declarar como un return type y que realmente podemos devolver como valor de return type.
- Declaraciones de return type:
- Return types en metodos sobre cargados:
La sobre carga de un metodo es solamente la reutilizacion del nombre. Por lo tanto podemos declarar cualquier tipo de return type que querramos. Pero debemos acordarnos de que a un metodo sobre cargado si o si le tenemos que cambiar la lista de argumentos - Sobre escribiendo un return type y returns covariantes:
Cuando queremos sobre escribir un metodo, la sub clase debe definir un metodo que concuerde exactamente con la version heredada del metodo. O en Java 5, tenemos permitido cambiar el return type siempre y cuando el nuevo sea subtipo del anterior.
- Return types en metodos sobre cargados:
- Devolucion de un valor:
6 Reglas:- Podemos devolver null en un metodo con return type que hace referencia a un objeto
- Un array es legar como return type
- En un metodo que devuelve un return type de tipo primitivo, podemo sdevolver cualquier valor o variable que pueda ser implicitamente convertida al tipo declarado de return type. (Ej: se declaro int y se devuelve char)
- En un metodo con un tipo de return type primitivo, podemos devolver cualquier valor o variable que pueda ser explicitamente catesado al tipo declarado. Ej: se declaro int y se devuelve un float, (int)f;
- No debemos devolver nada en un metodo que declara void en el return type.
- En un metodo con un return type que hace referencia a un objeto podemos devolver cualquier tipo de objeto que puede ser implicitamente convertido al tipo declarado. Ej: se declaro Animal y se devuelve Horse.
Constructores e Instanciacion:
Los objetos son construidos, por lo tanto no podemos crear a un objeto sin llamar a su constructor. Pero en realidad, no podemos hacer un objeto sin invocar no solo a su constructor, sino tambien a cada uno de los constructores de sus super clases. Cabe aclarar que para correr un constructor es necesaria la palabra clave new.
- Conceptos basicos de constructores:
Cada clase, incluyendo las clases abstractas, deben tener un constructor. En todos los constructores no hay return type. Y los nombres de los constructores deben coincidir con el nombre de la clase. Entonces es muy comun y deseable que la clase tenga un constructor que no reciba ningun argumento, sin importar cuantos constructores sobrecargados tenga la clase. - Encadenamiento de constructores:
Copiar ejemplo de Horse - Reglas para constructores: (si o si hay que saberlas)
- Los constructores pueden usar cualquier modificador de acceso, incluyendo private. ( si usamos private, solo podemos crear objetos dentro de la misma clase, por lo tanto la clase va a tener que proveer alguna metodo static o una variable que permita acceder a los objetos creados dentro de la clase.
- El nombre del constructor debe ser igual al de la clase. Si otra vez…
- No deben tener return type. Si tambien otra vez..
- Si no escribimos un constructor por defecto, lo genera automaticamente el compilador
- El constructor por defecto no debe recibir ningun argumento.
- Si escribimos otros constructores sobre cargados y queremos el constructor por defecto, debemos escrirlo nosotros, ya que si hay constructores, el compilador no genera nada.
- Todo constructor tiene como primer linea de su cuerpo o una llamada a su propio constructor (this()) o una llamada al constructor de su super clase. Esta llamada es insertada automaticamente por el compilador.
- No podemos llamar a un metodo de instancia, o acceder a una variable de instancia hasta despues de que el super() haya finalizado.
- Solamente podemo susar variables o metodos statics en la llamada del supe(). Ej: super(Animal.NAME);
- Las clases abstractas tienen constructores y son llamados siempre que una subclase concreta es instanciada.
- Las interfaces no tienen constructores.
- La unica manera de llamar a un constructo, es desde otro constructor. Por lo tanto no podemo sinvocar a un constructor desde un metodo, como si fuera otro metodo.
- Determinando cuando un constructor por defecto es creado:
- Cuando estamos seguros de que un constructor por defecto es creado?
Solamente cuando no hemos escrito ningun constructor dentro de la clase. - Como va a lucir el constructor por defecto generado?
- Tiene el mismo modificador de acceso que la clase.
- No recibe argumentos
- Incluye una llamada al constructor por defecto de la super clase sin argumentos
- Que pasa si el constructor de la super clase recibe argumentos?
Nos vemos obligados a escribir la llamada a super aplicando los argumentos necesarios.
- Cuando estamos seguros de que un constructor por defecto es creado?
- Para recordar:
- Los constructores nunca se heredan!
- Los constructores no son metodos!
- Por lo tanto no pueden ser sobre escritos!!
- Sobre carga de constructores:
Es cuando cambiamos la lista de argumentos de un constructor, generalmente para facilitar la tarea de los que invoquen a ese constructor.
Statics:
- Metodos y variables Static:
El modificador static tiene un profundo impacto en como se comportan las variables y los metodos marcados con static, por eso es tratado aparte de los otros modificadores.
Hacemos un metodo static, cuando la funcionalidad del metodo siempre va a ser la misma, y esta es independiente de la instancia (valores de las variables de instancia). Tambien podemos hacer mension al tipo ejemplo de contar la cantidad de instancias de un tipo de objeto en particular. Donde guardamos el contador?
Las variables y los metodos marcados con static pertenecen a la clase y no a ninguna de sus intancias particulares.
Por esto si hay muchas intancias de una clase que tiene variables static, esta variable se comparte para todas las intancias, existiendo en realidad una sola copia para todas las intancias.
Hay que recordar que un metodo static no puede acceder a una variable no static (de instancia) ya que no hay instancia asociada al metodo! - Accediendo a metodos y variables Static:
La manera de acceder a una variable o metodo static, es usando el operador punto (.) sobre el nombre de la clase directamente, lo opuesto seria sobre una variable de referencia a un objeto instanciado de la clase.
Pero para hacerlo realmente confuso, el lenguaje Java tambien nos permite usar una referencia a un objeto para llamar a los metodos y variables static. Y esto es solamente un truco de sintaxis ya que el miembro static sigue sin conocer a la instancia en particular del objeto que uso para llamar a los metodos o variables.
Finalmente hay que recordar que los miembros static no puede ser sobre escritos. Esto no significa que no se puedan redefinir en la subclase.
Hay que recordar tambien que a la hora de llamar a un metodo static con una variable de referencia, se resuelve que metodo ejecutar en el arbol de herencia basandose en el tipo de la variable de referencia y no de la instancia creada.
Acoplamiento y Cohesion:
Estos dos temas tiene que ver con la calidad del disenio orientado a objetos. En general se dice que es un buen disenio Orientado a Objetos cuando posee bajo acoplamiento y alta cohesion. Y esto nos brinda las siguientes ventajas:
- Facil creacion
- Facil mantenimiento
- Facil mejoramiento y adecuacion
- Acoplamiento:
Es el grado en que una clase sabe de otra clase. Si el conocimiento de una clase A sobre una clase B, es lo que la clase B expuso a travez de su interfaz, entonces se dice que A y B estan bajamente acopladas, y esto es bueno. - Cohesion:
Mientras que el acomplamiento habla sobre como interactuan unas clses con otras, la cohesion habla de como una sola clase es diseniada. El termino cohesion idica el grado en que una sola clase esta bien enfocada en un proposito.
El mayor beneficion de una alta cohesion son las clsaes mucho mas faciles de mantener.
Hardy Heron Final Version!
Marzo 15, 2008
Ya faltan menos de 40 dias para el realease oficial de Hardy Heron! La nueva version de Ubuntu!
Para los que no puedan esperar aca les dejo los repositorios todavia en beta para que puedan hacer su distro upgrade!
/etc/apt/source.list:
deb http://archive.ubuntu.com/ubuntu/ hardy main
Manic Street Preachers – Know Your Enemy
Marzo 15, 2008

Musica que no pasa de moda
Se me pianta el lagrimon! PSB -> Flamboyant!
Marzo 14, 2008
Sin palabras…
SCJP – Capitulo 2: Orientacion a Objetos (Parte #1)
Marzo 13, 2008
2 grandes beneficios que obtenemos de la Orientacion a Objetos son flexibilidad y mantenimiento.
Encapsulacion:
La mayor ventaja de la encapsulacion es que podemos hacer comabio en la implementacion sin romper el codigo de otros, ya que escondemos la implementacion detras de interfaces publicas de programacion.
Si queremos mantenibilidad, flexibilidad y extensibilidad nuestro disenio debe incluir encapsulacion Como logramos esto?
- Mantenemos las variables de instancia protegidas (private)
- Creamos accesors publicos para las variables de instancia
- Usamos la convencion de getters y setters
Herencia: (IS-A y HAS-A)
Todas las clases en Java heredan de la clase Object por eso en todas tenemos los metodos equals, clone, notify, wait, etc.
Para el examen tenemos que saber crear relaciones de herencia y entender los usos comunes de la herencia:
- Promover la reutilizacion de codigo(mediante codigo generico)
- Usar polimorfismo
Relacion IS-A:
El concepto esta basado en la herencia de una clase o la implementacion de una interfaz. Esto quiere decir que en Java indicamos una relacion IS-A con las palabras claves extends e implements.
Relacion HAS-A:
El concetp esta basado en el uso. En otras palabras la clase A HAS-A B si en el codigo de la clase A se hace referencia a una instancia de B.
Polimorfismo:
Cualquier objeto que pase mas de un test IS-A (con el operador instanceof) es considerado polimorfico. Hay que recordar que la unica manera de acceder a un objeto es mediante una variable de referencia y por esto vamos a recordar algunas cosas de ellas:
- Una variable puede ser de un solo tipo, y una vez declarado este tipo no puede cambiar.
- Una variable de referencia puede ser reasignada a otro objeto (a menos que haya sido declarada final)
- Una variable de referencia determina que metodos pueden ser invocados en el objeto que la variable referencia.
- Una variable de referencia puede referirse a cualquier objeto del mismo tipo o subtipo del tipo que se declaro la variable!!!
- Una variable de referencia se puede declarar del tipo de una interfaz y hacer referencia a cualquier objeto que implemente esa interfaz!!!
La JVM en runtime sabe de que tipo es exactamente el objeto (aunque lo estemos referenciando con una variable de tipo interfaz o una super clase) y por lo tanto si hay un metodo sobre escrito, se ejecuta el codigo del metodo del objeto realmente y no el de la super clase.




