Skip to content
Juan-Pablo Silva edited this page Aug 19, 2019 · 11 revisions

Preguntas frecuentes y dudas

Polimorfirmo

Basicamente responde a lo que naturalmente nosotros entendemos como correspondencia de tipos. Por ejemplo: una casa es una construccion, un edificio es una construccion, una persona no es una construccion. La casa y el departamento se parecen porque tienen murallas y vive gente en ellos, pero aun asi son distintos ya que cada uno se especializa de distinta forma.

Otro ejemplo muy clasico somos nosotros mismos. Tenemos un tipo superior, Seres Vivos. Los seres vivos, naturalmente, pueden morir. Bajo los Seres Vivos tenemos los Animales, Plantas, Insectos, etc. Dentro de los Animales estamos los Humanos. Dentro de los Humanos tenemos mas cosas, Estudiantes, Trabajadores, Bebes, etc. Todos pueden ser considerados Seres Vivos, a pesar de tambien ser Humanos. Un Estudiante puede ser tratado como Humano ademas de ser un Estudiante. Hay acciones y caracteristicas comunes para todos. Por ejemplo los Humanos pueden alimentarse al igual que las Plantas. La forma en que lo hacen es distinta, pero bajo cierto contexto, las Plantas, Insectos y Humanos pueden considerarse como lo mismo para hablar de algo mas general, como un Ser Vivo.

Formalmente el polimorfirmo se define de la siguiente forma: Es la capacidad de un tipo A, de verse y poder usarse como otro tipo B.

Clase vs Objetos

Una clase define es esqueleto de un objeto. Piensen en la clase como un cortador de galletas. La forma seguramente sera la misma, pero el sabor de la masa, el color y las decoraciones seran potencialmente distintas. Aun asi, todas estas galletas seran, pues, galletas, a pesar de que sean distintas, todas comparten la misma forma y caracteristicas generales.

Mas formalmente, una clase define los datos y procedimientos disponibles par aun cierto tipo o "clase de objeto". Mientras que un objeto corresponde a la instancia de una clase.

Metodo vs Funcion

Hay unas diferencias bien sutiles en el uso del lenguaje en la programacion orientada a objetos, y en particular en nuestro contexto en Java. En Java nosotros tenemos metodos, no funciones.

En los lenguajes orientados a objetos tenemos, bueno, objetos. Los objetos tienen metodos, que son distintos a una funcion. Las funciones en lenguajes como Python, C, y amigos, son trozos de codigo que modifican el estado del programa. Son subrutinas que estan desasociadas de las estructuras o datos sobre que actuan. Estan ahi sueltas y reciben cosas, luego hacen lo que saben hacer y retornan. Los metodos no son asi, los metodos son subrutinas asociadas al objeto mismo y funcionan a nivel de objeto, no del programa, pueden acceder al estado interno de los objetos, y sus valores de salida, flujos de operacion y resultados pueden variar completamente dependiendo del estado interno del objeto en cuestion, independiente del estado global del sistema.

Basicamente cada objeto tiene sus propias operaciones que se llaman metodos, las funciones son cosas a nivel del programa o clase.

Mensajes

Los mensaje comunmente se confunden con lo que tanto conocemos como "llamar funciones", "invocar funciones", "hacer una llamada", etc. pero en verdad son un poquito mas que eso en los lenguajes orientados a objetos (como java).

Entonces, que es eso de mandar un mensaje? Cada objeto tiene formas de comunicarse con el mundo, que serian los metodos. Entonces cuando nosotros queremos comunicarnos con un objeto, le enviamos un mensaje, ese mensaje es una llamada a un metodo. No le invocamos una funcion, sino que le enviamos un mensaje para que el objeto vea como lo interpreta y vea como actuar.

Suena a lo mismo? Son parecidos, pero imagina con herencia. Si estuvieras "llamando una funcion", es una funcion especifica, el objeto no decide, tu decides que funcion llamas. No queremos eso (no regularmente al menos), entonces le mandamos un mensaje diciendole que queremos ejecutar cierto metodo. Luego el objeto ve que metodo invoca, porque pudo haber un metodo en la super clase y ahora lo esta sobrescribiendo, por decir algo. La diferencia mas notoria esta en que una funcion corresponde a una accion que tu manualmente estas ejecutando y llamando. Un metodo corresponde aun mensaje que se le envia a un objeto, para que este determine como actuar al recibir esa "orden", podria incluso hacer nada en caso de que asi haya sido configurado.

Referencia vs Puntero

Esta respuesta es un poco mas tecnica respecto al uso de memoria dentro del diseño del lenguaje.

En lenguajes donde se permite el manejo manual de memoria, como C, un puntero se refiere a una direccion de memoria donde se encuentra un valor. No al valor en si, sino mas bien donde esta guardado ese valor. Fijarse en la terminologia, un valor. Este puntero puede apuntar a cualquier cosa, ya que en verdad a este no le importa lo que haya dentro de esa direccion de memoria.

Una referencia en cambio apunta solo a objetos. Los objetos no son cualquier cosa, son estructuras complejas compuestas de metodos, variables, datos de herencia, configuraciones y mas referencias.

Modelar un objeto en C

Independiente de lo dicho en la respuesta de Referencia vs Puntero, uno puede simular un objeto en C mediante structs. Por su puesto, esto no es lo mismo, pero es una simulacion.

struct person {
    int (*eat)(void *);
};
struct person onePerson;

onePerson.eat(apple)

Aqui tenemos una estructura person, que tiene un puntero a una funcion eat que recibe 1 parametro, que es un puntero a "cualquier cosa". Luego podemos llamar a la funcion eat como si onePerson fuera un objeto, pasando alguna variable apple.

Las desventajas de esto son claramente que la funcion eat no esta definida dentro de person, person solo contiene un puntero a esta.

== vs .equals()

Construyendo sobre que ya entiende el concepto de referencia, la diferencia es la siguiente: == compara referencias, que si los trozos de memoria definidos por lo objetos comparados son la misma. En cambio .equals() llama al metodo equals definido en la clase Object. Por defecto, Object hace exactamente == entre los objetos comparados. Pero como sabemos, si es un metodo, podemos especializarlo. En este caso, hacemos un Override de equals y definimos las condiciones explicitas en las cuales consideramos que un objeto es igual a otro. Puede ver un ejemplo de esto en el siguiente link del repositorio: java/objects.

Recuerde que se pide expresamente que si se hace override a equals, este debe ir acompañado de un override a hascode. Este ultimo metodo se usa para encontrar la representacion del objeto al momento de insertarlo en algun mapa o representacion de hash. Si no define esto, puede caer en bugs del estilo:

...
Map<CustomObject, Integer> mapa = new Hashmap<>();
CustomObject object1 = new CustomObject();
CustomObject object2 = new CustomObject();

System.out.println(object1.equals(object2)) // -> retornaria true

mapa.put(object1, 100); // se agrega object1
mapa.put(object2, 1000); // se agrega object2
// se supone que ambos objetos son el "mismo" objeto (definido por nosotros), pero...
System.out.println(mapa.get(object1)) // -> retornaria 100
System.out.println(mapa.get(object2)) // -> retornaria 1000

Como puede ver el valor no se reemplazo. Esto puede ser intensional, pero en caso de no serlo, es un bug que en un software grande y complejo, es casi imposible de diagnosticar y puede causar gigantes dolores de cabeza.