Introducción
Este artículo funcionará como la parte práctica del artículo anterior sobre Clases en Programación. Vamos a resolver un ejercicio sobre estructura de clases y a implementarlo en C# en Unity.
Si no sabés qué es una clase en programación estaría bueno que veas el artículo que escribí sobre el tema antes de continuar.
🟢 VÍDEO: Acerca del concepto de «CLASE» en programación orientada a objetos
Planteo del ejercicio
Vamos a ver un ejemplo que se me ocurrió al momento de escribir este artículo. Se trata de modelar el comportamiento de una aldea que tiene habitantes y estos habitantes pueden ser aldeanos que trabajan o guerreros que luchan.
He resaltado lo que considero palabras claves en el planteo del problema, en principio parece que al menos vamos a necesitar dos clases para resolverlo, una para la aldea y otra para los habitantes, pero vamos a considerar el hecho de que tanto aldeanos como guerreros en sí son habitantes.
Aldeanos y Guerreros tendrán características y comportamientos comunes que estarán definidos en la clase Habitante y luego las clases Aldeano y Guerrero heredarán las características y comportamientos de Habitante.
Una aldea tiene habitantes por lo que la clase Aldea tendrá entre sus datos una o más instancias de la clase Habitante.
Quisiera mencionar que el hecho de conocer la diferencia entre clases e instancia de clases es importante muy importante, pero este artículo no trata sobre eso así como tampoco trata sobre herencia.
De momento la idea es que vamos a usar la clase Habitante para a crear todos los objetos Habitante que necesitemos, estos objetos tendrán sus propios valores (por ejemplo nombres o edad distintas) pero en sí respetarán la estructura definida en la clase.
Diagrama de Clases
Entonces dijimos que vamos a usar cuatro clases, Aldea, Habitante, Aldeano y Guerrero. La clase Aldea tiene entre sus datos una o más instancias de la clase Habitante. Aldeano y Guerrero son un tipo específico de Habitante por lo que se usará herencia.
El diagrama de clases de la figura 1 está basado en el párrafo anterior.
En el diagrama observamos un «1..*» encima de Habitante, esto quiere decir que Aldea tendrá uno o más objetos Habitante.
Además observamos que la herencia de clases se representa con una flecha ascendente hacia la clase padre.
Diagrama de Objetos
Una vez definida las clases que estarán presentes pensamos en sus posibles campos y métodos, en esta parte está bueno reflexionar sobre la naturaleza del objeto que queremos modelar, cuáles son sus características, qué información maneja y cuál puede ser su comportamiento.
Voy a inventar algunos campos y métodos para las clases porque esta práctica de clases de programación se trata más que nada sobre el planteo de estructura de clases y su posterior implementación en Unity en lenguaje C#, pero sin entrar en detalles de qué se va a hacer con esto.
En la figura 2 se ven los diagramas de objeto de las cuatro clases.
Ahora voy a pasar a explicar en detalle cómo se interpretan las cajas de la figura 2.
El objeto Aldea
Para este objeto consideré que toda aldea tiene un nombre y un grupo de habitantes, así que para sus campos voy a usar una colección de objetos Habitante llamada «habitantes», un string llamado «nombre» y un entero llamado «poblacion». Estos campos los coloco en la parte de arriba de la caja como vemos en la figura 2.1.
Algunos métodos del objeto Aldea pueden ser «NuevoHabitante» que se ejecutará cada vez que nazca un habitante. «ObtenerNombre» y «ObtenerPoblacion» que nos devolverán los datos correspondientes (se conocen como «Getters» y son útiles por ejemplo para hacer estadísticas de todas las aldeas que podamos tener).
El método «MuereHabitante» se puede encargar de modificar la población y eliminar el habitante muerto de la colección de habitantes.
Por último el método «AlimentarHabitantes» que puede recorrer la colección de habitantes ejecutando métodos apropiados en cada uno de ellos, o chequear la reserva de comida y restar tantas unidades como población haya.
El objeto Habitante
Habitante va a ser la clase padre (o superclase) de Aldeano y Guerrero, en esta clase estará definido el comportamiento y los datos que tengan en común Aldeanos y Guerreros.
Todo habitante tiene un nombre representado por un String, un entero para la edad, otro para la salud y otro para la defensa.
Entre los métodos de Habitante tenemos los «Getters» para obtener nombre y edad, un método privado para envejecer y un metodo público para que el habitante se mueva a una posición.
El objeto Aldeano
El objeto Aldeano es un caso más específico de la clase Habitante, entre sus campos tenemos un string que indica el nombre del trabajo y una variable booleana para saber si se encuentra trabajando o no.
Los métodos de Aldeano están relacionados a lo que podrían ser sus actividades, por ejemplo Recolectar, Reparar, Talar, Pescar y también un método privado para que entregue los recursos que haya conseguido. Este último método lo puede ejecutar internamente Aldeano por ejemplo cuando esté al límite de su capacidad de recolección.
El objeto Guerrero
La clase Guerrero es un caso más específico de la clase Habitante.
Un Guerrero puede estar atacando o no para lo que usamos la variable booleana «atacanado», tiene asignada un arma representada por un String y tiene ciertos puntos de ataque representados por una variable entera.
Entre sus métodos tenemos Atacar, Formacion, Defenderse y un método privado para entregar el botin que obtuvo después de salir exitoso de una batalla.
Implementación en Unity
Ahora pasamos a la parte buena, vamos a tomar el diagrama de clases y el diagrama de objetos de las figuras 1 y 2 y utilizarlos como referencia para crear las clases en Unity.
Antes de empezar tal vez necesitás saber cómo usar Unity, acá en la página tengo un par de series, una llamada «Fundamentos de Unity» y la otra «Juego del Laberinto«, la primera tiene temas específicos y la segunda es un mini proyecto. Podés encontrar todos los artículos usando el menú de navegación y también están los videos en el canal.
Sigamos, en un proyecto de Unity creamos las cuatro clases del diagrama de la figura 1.
Por convención los nombres de las clases comienzan con mayúscula y se utiliza CamelCase si el nombre de la clase tiene más de una palabra. Por ejemplo la clase «Arma de Largo Alcance» podría escribirse «ArmaLargoAlcance», mejor aún si nos acostumbramos a usar nombre en inglés «LongRangeWeapon».
Una aclaración, como se vio en el artículo: «¿Qué es una Clase en Programación?», al crear una nueva clase en Unity, esta va a heredar de MonoBehaviour, lo que permitirá que Unity la considere en su ciclo interno. Vamos a dejar esta herencia así como está, aunque no lo hayamos explicitado en el diagrama de clases de la figura 1.
Si quisiéramos hacer un diagrama más acertado deberíamos colocar la clase MonoBehaviour y hacer que tanto Aldea como Habitante hereden de ella.
Como aclaración está bueno decir que nuestras clases van a ser MonoBehaviours, sin embargo no tiene sentido plantear un diagrama de clases extremadamente completo ya que MonoBehaviour hereda de la clase Behaviour, que a su vez hereda de la clase Component, quien finalmente hereda de la clase Object. No es necesario ir tan lejos, hay que enfocarnos en lo importante para resolver nuestro problema.
La clase Aldea
Para escribir el cógido correspondiente en la clase Aldea debemos mirar el diagrama de Objeto de Aldea y simplemente conocer la sintaxis del lenguaje orientado a objetos que vamos a utilizar, en este caso C#.
En la figura 4 vemos cómo se implementac lo especificado en el diagrama de la figura 3.1 utilizando lenguaje C# en Unity.
Noten cómo se respetan los nombres, los tipos de datos y la visibilidad indicada en el diagrama de objetos.
Esta es la idea de la práctica de Clases en programación, crear clases en Unity basándonos en un análisis del problema y los diagramas de clases y objetos.
No vamos a escribir nada en los métodos porque es algo que depende de cuál es la finalidad de la solución que estamos planteando.
La clase Habitante
La clase Aldeano
La clase Guerrero
Conclusión
En esta práctica de Clases en Programación hemos visto cómo a partir del planteo de un problema proponemos una estructura de clases para modelar el comportamiento de los elementos.
La estructura de clases la representamos utilizando un Diagrama de Clases en el que mostramos cuál es la relación que existe entre ellas.
Las Clases tendrán sus miembros, es decir Campos y Métodos, podemos representarlos utilizando Diagramas de Objetos, en los que mostramos nombres y tipos de datos para los Campos y los métodos que tendrá la clase. Además la visibilidad de cada uno.
Todo lo anterior es independiente del lenguaje de programación, se trata sobre modelar de manera intuitiva una solución orientada a objetos.
Para implementarlo en Unity en lenguaje C# deberemos conocer la sintaxis propia del lenguaje, sin embargo es sumamente interesante saber que esto mismo se podría reutilizar por ejemplo para una aplicación Android utilizando lenguaje Java en Android Studio.