Saltar la navegación

Caso práctico. Creamos un ejército

Caso práctico

Tras todo lo aprendido en los seis capítulos anteriores podemos empezar a hablar de la programación orientada a objetos. Este tema va a ser tratado únicamente en este capítulo y tiene una gran relevancia, pero al mismo tiempo requiere ciertos conocimientos de programación y no se puede llegar al verdadero potencial, aunque sí se puede vislumbrar y trataré de que lo consigas ver. Intenta a lo largo del capítulo entender cómo la programación orientada a objetos puede ser de ayuda para usarla en el futuro.

Comencemos, imagina que quieres hacer un juego de batallas en una tierra fantástica. En dicho juego hay un montón de cosas que tienes que crear: elfos, enanos, humanos, orcos, caballos, espadas, hachas... Pues bien, todas esas cosas que deberías crear para el juego son llamadas, en programación, objetos. Por lo tanto, a partir de ese momento, al ir creando el juego empezarás a enfocar tu programación a los objetos, es decir, necesitarás programar qué hará cada uno de los humanos (ya que cada uno será un objeto), cada elfo, cómo interactuarán, qué aspecto tendrán, que tamaño... Pues bien, todo ello, así, de forma muy resumida, es la programación orientada a objetos. Dicha programación se enfoca a algo más que variables, listas y diccionarios, se enfoca a objetos completos que tienen sus propias variables, sus propias listas... Ahora que entendemos qué es un objeto, vamos a centrarnos en ellos. Un objeto se puede describir (¿cómo es?) y puede hacer cosas (¿qué habilidades tiene?). Pongamos, siguiendo con el ejemplo, que quiero crear un elfo. El elfo tendrá un tamaño, un peso, una fuerza... es decir, se puede describir o tiene atributos. El elfo también podrá correr, saltar... es decir, podrá realizar acciones.

En programación, a los atributos de un objeto los denominaremos propiedades.
Así mismo, a las acciones que puede realizar un objeto las denominaremos métodos.
Además de todo lo anterior, los objetos se pueden agrupar por tener propiedades y métodos similares. Sigamos con el ejemplo: un elfo tendrá un nombre, una fuerza, una altura... pero un humano también tendrá un nombre, una fuerza y una altura. Por ello, a los objetos que comparten propiedades y métodos se les denominan clases.

CLASES:

Todos los objetos que comparten propiedades y métodos se pueden construir desde un mismo modelo. Imagina que quieres hacer un ejército de elfos, enanos y humanos y necesitas describir a todos los soldados de una forma un poco genérica, podrías decir que...

Todos los soldados tienen una raza
Todos los soldados tienen un nombre
Todos los soldados poseen una fuerza
Todos los soldados son capaces de correr a una velocidad
Todos los soldados tienen un arma

Pues bien, a un modelo que representa a un conjunto de objetos se le denomina clase.
Recopilemos: una clase es un modelo que define a una serie de objetos similares que, simplificando, se puede decir que son cosas. De esta forma, podemos tener la clase soldado, que será un modelo para definir a una serie de soldados que tendrán una raza, una fuerza, podrán correr... También podríamos tener la clase piedra que tiene un tamaño y puede romper el dedo meñique de los soldados cuando van descalzos.
Vamos a trabajar con el ejemplo de los soldados ya que es habitual en la programación de videojuegos. Haremos un script que permita crear diferentes soldados que podrían ser usados en un hipotético juego.

CREAMOS UNA CLASE
En Python, para crear una clase no hay más que indicarlo de la siguiente forma:
class Soldado:
Si te fijas, al definir la clase, he usado una palabra con la primera letra en mayúscula. Si bien no es obligatorio, en programación se suelen llamar a las clases con la primera letra en mayúscula para diferenciarlas de variables, listas o diccionarios. Con la instrucción anterior estás creando un modelo o esquema de cómo va a ser cualquier objeto que sea de la clase Soldado. Luego podrás crear tantos objetos Soldado como quieras, pero al declarar una clase nomcreas ningún Soldado, sólo especificas cómo son esos objetos.
Para llamar a una clase sólo hay que almacenarla en una variable y añadir tras el nombre unos paréntesis:
#Creo mi primer soldado e indico que es de la clase Soldado
             soldado1 = Soldado()
Es normal, al principio, tener dificultades para entender la diferencia entre una función y una clase. Una función es un trozo de código que se aloja bajo un nombre para poder ser usado en cualquier momento. Al llamar a una función, el programa reproduce su código y cuando termina deja de estar, aunque nos puede entregar valores que sí permanezcan. En cambio, una clase, al ser llamada, crea un objeto que puede ser almacenado y permanecerá listo para ser usado en cualquier momento.

CREAMOS EL CONSTRUCTOR

Al crear nuestra clase Soldado la hemos dejado un poco huérfana de propiedades y métodos. Veamos cómo podemos definir ese esquema o modelo de Soldado. Al crear la clase lo primero que debemos crear es lo que se denomina constructor, que contendrá todo aquello que deba contener el objeto al ser creado. El constructor se ejecutará automáticamente al crear un objeto de la clase en la que se encuentra. Imagina que te toca construir Soldados y tienes que crearlos en su forma más básica para ser entrenados y convertidos en verdaderas armas de guerra. En el constructor introduciremos todos esos atributos que deba tener cada soldado (raza, nombre, vida...). El constructor hay que definirlo de la misma forma que definíamos las funciones hace unos capítulos. Para indicar que estamos definiendo el constructor debemos usar __init__ (con doble barra baja antes y después de init):
class Soldado:
#Definimos el constructor, es decir, la función __init__     def __init__():
Si recuerdas, en las funciones podíamos pasar parámetros. En el caso de las funciones que van dentro de una clase (y el constructor es una de ellas) también podemos enviar parámetros, aunque no es obligatorio hacerlo. Eso sí, hay un parámetro que siempre debemos introducir: self o, en castellano, yo. Como hemos dicho antes, el constructor se ejecutará nada más crear un objeto de la clase que lo contiene, no hace falta llamarlo para que se ejecute, como pasaba con las funciones. Ahora que ya sabemos lo que es un constructor, vamos a ver cómo lo creamos de forma que contenga lo necesario para nuestros soldados. Al constructor que creará nuestros soldados le vamos a pasar dos parámetros: raza y nombre.
class Soldado:
#Situamos los parámetros que queremos y el obligado self al principio  def __init__(self, nombre, raza):
Si no lo tienes claro piensa que el objeto, al ser creado, necesita para darle sentido a su existencia ciertos parámetros básicos. Eso no quiere decir que no se pueda crear un objeto sin pasar ningún parámetro. Yo podría crear una clase Soldado en la que, al ser materializada como objeto (es decir, llamada) todo soldado tuviese la misma vida, nombre y raza, pero no tiene mucho sentido hacer un ejército de clones y ponerles a todos el mismo nombre. El general iba a tener ciertos problemas en el campamento cuando llamase al centro de mando a Légolas y viniesen 50.000 Légolas. Una vez tenemos los parámetros que vamos a pasar a la clase para crear un objeto toca programar qué hacemos con esos parámetros. En nuestro programa el parámetro nombre llegará desde una variable que contenga un nombre para el soldado. Lo mismo ocurrirá con el parámetro raza, aunque ambos podrían ponerse como strings directamente al crear el objeto Soldado.
Observa el siguiente código y trata de entenderlo con el párrafo que lo explica tras el mismo:
class Soldado:
#Situamos los parámetros que queremos y el obligado self al principio
def __init__(self, nombre, raza):
         self.nombre = nombre
Empecemos con el parámetro nombre. Para usar un parámetro y aplicárselo al objeto debemos usar, de nuevo, self. Vamos a indicar al objeto que, al ser creado, el parámetro que le llega llamado nombre lo tiene que almacenar en una variable propia llamada nombre. A mí las primeras veces que me enfrenté a este tipo de estructura casi me explota la cabeza. Con el tiempo la normalizas y te parece de lo más razonable, pero es cierto que conviene pararse a explicar qué está pasando. Vamos a ver un esquema:
#Creamos un Elfo llamado Eldelbar
nombre = "Eldelbar"
raza = "Elfo"
primer_soldado = Soldado(nombre, raza)
Al llamar a Soldado primero se ejecuta la función __init__( ):
def __init__(self, nombre,raza)
            self.nombre = nombre
La cual está recibiendo los siguientes parámetros del programa:
def __init__(self, "Eldelbar","Elfo")
            self.nombre = "Eldelbar"
En la construcción de la clase decimos que al crear un objeto van a llegar dos parámetros, uno que llamamos nombre y otro que llamamos raza. Al crear un objeto, nombre tendrá un valor (en nuestro ejemplo “Eldelbar”) que vamos a guardar en la variable nombre propia del objeto (que no tiene nada que ver con la variable nombre en la que almacenamos al principio el nombre Eldelbar. Bueno, sigamos con nuestro constructor. Una vez tenemos el nombre para nuestro recién creado primer_soldado vamos a incorporar la raza también como variable interna del objeto:
class Soldado:
         def __init__(self, nombre, raza):
                   self.nombre = nombre
                   self.raza = raza
Como verás, el mecanismo es el mismo exactamente que con el nombre. Ya tenemos dos variables propias del objeto. Ahora vamos a ver cómo podemos acceder a ellas. Para acceder a cualquiera de las propiedades de una clase, tenemos que hacerlo con el nombre con el que se creó el objeto con el siguiente comando:  nombre_objeto.nombre
Vamos a ver cómo podríamos crear un soldado llamado Eldelbar e imprimir su nombre y su raza tras crearlo. En esta ocasión no vamos a pasar los parámetros como variables sino directamente escribiremos los string que correspondan al nombre y raza al usar la clase Soldado. Guarda el siguiente código en un script y ejecútalo desde VsCode o Trinket

Creado con eXeLearning (Ventana nueva)