Hola y bienvenidos a la segunda parte de nuestro video sobre asociaciones. Al final de este video podrás leer diagramas de clases que contengan asociaciones simples, entender sus roles, su navegabilidad, diseñar métodos que utilizan estas asociaciones y cómo se declaran e implementan en lenguajes de programación orientados a objetos. Tenemos un ejemplo, cursos y estudiantes. Modelamos la clase "Estudiante" y la clase "Curso", y definimos una asociación que representa los cursos vistos por un estudiante, y la vamos a llamar "vistos Por". Vamos a modelar que un curso puede no tener estudiantes o tener muchos estudiantes y que un estudiante está viendo al menos un curso. Esto es la cardinalidad. Sin embargo, no sabemos todavÃa cómo participa cada objeto en la relación, y esto es lo que vamos a definir ahora y lo que denominamos el rol de la asociación. Y a través de estos roles vamos a aumentar la precisión de nuestra abstracción del problema. Entonces, los roles se ubican a cada extremo de una asociación y se nombran de manera explÃcita describiendo el rol que juega el objeto en la relación muy claramente. Por ejemplo, de este lado están los cursos que está viendo un estudiante, asà que nombraremos el rol de la clase Cursos como "cursos Vistos", mientras que del lado de la clase estudiante el rol será "estudiantes Inscritos". Esto nos permite describir entonces que un estudiante tendrá varios cursos inscritos y por eso hemos usado el "por" y, a su vez, un curso tendrá varios estudiantes inscritos que lo están viendo. Notemos entonces que los roles se nombran con su primera letra en minúscula y respetando "Camel Case" para cuando el nombre está compuesto por varias palabras. Además, el nombre del rol es bastante significativo de la relación que existe entre ambas clases, ¿no están de acuerdo? Veamos ahora otro concepto. Otra manera de aumentar el nivel de especificidad y detalle de una relación es emplear navegabilidad. La navegabilidad es una manera de describir cómo las instancias de una clase pueden acceder las unas a las otras. La manera de indicar la dirección de la navegabilidad es dibujando una flecha sobre la lÃnea. Las instancias del lado de la punta de la flecha podrán ser accedidas por las instancias del principio. Lo contrario no es posible. Cuando no se indica una punta de flecha, como en nuestro ejemplo, se asume que la navegabilidad es bidireccional. Esto significa que las instancias relacionadas pueden verse mutuamente. Asà que vayamos a un ejemplo diferente. Imaginemos una clase "Salón" y una clase "Curso". Un curso puede ser dictado en uno o varios salones, y esto es la cardinalidad. Y dentro de nuestra abstracción tiene sentido que, si bien podamos acceder a los salones desde las instancias de un curso, lo contrario sea menos práctico y, por ende, determinamos que hay una navegabilidad unidireccional en dirección de la clase Salón. Miremos un ejemplo usando otro tipo de instancias, y traigamos de regreso a Juan y MarÃa de nuestros vIdeos sobre sintaxis básica de clases. Ambos son instancias de la clase Estudiante. Ahora, creemos una instancia de la clase Curso y este curso será "Introducción a UML". Lo que define nuestra navegabilidad es que del lado de las instancias de la clase Curso, "Introducción a UML", este puede acceder a sus estudiantes Juan y MarÃa si están inscritos en él, obviamente. Del lado de los estudiantes, Juan y MarÃa pueden acceder a su curso de Introducción a UML. Si limitáramos la navegabilidad desde la clase Estudiante hacia la clase Curso, Juan y MarÃa podrÃan ver la instancia de Curso, pero este curso no sabrÃa ni tendrÃa acceso a sus estudiantes. Y si hacemos lo inverso, si definimos una navegabilidad de curso Estudiante, "Introducción a UML" podrÃa tener acceso a Juan y MarÃa, pero estos no tendrÃan acceso a su curso. Entonces es posible que te estés preguntando aquÃ, en un lenguaje de programación orientada a objetos, por ejemplo Java, donde no existe el concepto explÃcito de asociación, ¿cómo las implementamos? La respuesta es ésta, se implementan definiendo atributos de cada clase de la asociación de acuerdo con los roles y la navegabilidad. Vayamos a nuestro ejemplo una vez más. En la clase Estudiante, debemos declarar como atributo una colección de objetos de tipo curso de nombre "cursos Vistos" en el que estarán registrados todos los cursos vistos por los estudiantes. Y en la implementación, tendremos que garantizar que este arreglo debe tener siempre al menos un objeto. Por otro lado, en la clase Curso declaramos una colección de objetos de tipo estudiante llamado "estudiantes Inscritos". Y si tenemos una navegabilidad indicada en dirección de los estudiantes, solamente tendremos la colección "estudiantes Inscritos" del lado de los cursos, pero no tendremos la colección "cursos Vistos" del lado de los estudiantes debido a lo que mencionamos anteriormente. Si tuviéramos una asociación con cardinalidad de uno, en lugar de tener una colección, tendrÃamos un atributo de la clase que está al otro lado de la asociación. Miremos el ejemplo de una clase "Universidad" y una clase "Estudiante". Un estudiante sólo puede estudiar en una universidad, asà que su cardinalidad es uno. Del lado de la clase Estudiante, debe existir entonces un atributo de la clase Universidad que según el rol se llama "Universidad" y que modela la universidad en la que estudia. Estas decisiones de modelado van a variar dependiendo de cada problema, pero es importante que reflejen lo más precisamente posible el contexto que estamos tratando de abstraer. Es importante notar que, una vez que tomamos una decisión y la modelamos, quien la lea interpretará el modelo en consecuencia, es decir, exactamente igual a la decisión que tomamos. Significa que de esta forma podemos validar el entendimiento del problema. Pongamos un ejemplo. Sobre este diagrama leo que un estudiante debe estar inscrito en, al menos, un curso. Cuando validamos el modelo, los responsables pueden aceptar esto o decirnos, si es el caso, que un estudiante podrÃa no estar inscrito en ningún curso, por lo que deberÃamos modificar la cardinalidad. Ahora hablemos un poco más de los métodos. En otros videos anteriores vimos que podÃamos definir el comportamiento de las clases a través de métodos y vimos algunas operaciones básicas como retornar o cambiar el valor de un atributo. Tener un modelo que crece en complejidad nos permite pensar también en métodos que, a su vez, son de mayor complejidad, que representan cómo se comportan los objetos en relación a las asociaciones que hemos definido. Pensemos en un método para la clase Estudiante que se llama "registrar Curso" y que recibe como parámetro un objeto de tipo Curso. Este método agregará un nuevo curso para el estudiante en su lista de cursos. Podemos incluso idear métodos más complejos con más parámetros, quizás un método "cambiar Curso" que reciba una cadena de caracteres y un curso, que le permita al estudiante cambiar el curso del nombre que viene como primer parámetro, por uno que se le envÃa como segundo parámetro. Podemos aquà ver cómo podemos enviar uno o varios parámetros al momento de crear un método, y eso nos va a permitir aumentar la complejidad de los comportamientos que modelamos. Con esto termina nuestro tema de las asociaciones simples y los métodos. TodavÃa hay mucho que ver y mucho que contar, pero por ahora te invito a que pases a trabajar en la construcción de modelos usando asociaciones, y te espero para la próxima en donde hablaremos de nuevos tipos especiales de asociaciones. Nos vemos.