Clases

Las clases sirven como una plantilla para crear objetos.

¿Qué es un objeto?

Es un conjunto de datos que permite describir a una persona, animal, cosa o concepto en especifico. Puedes revisar la página de Objetos para más información.

¿Cuál es la diferencia entre clase y objeto?#

Con la clase puedes crear múltiples objetos que sean estructuralmente idénticos a esa clase. Cada objeto puede tener sus propios datos independientes.

Objetos vs. Clases

Los objetos son como una fotocopia de la clase. Si modificas los datos de un objeto, no afectará a los demás objetos. Si modificas la clase, afectará a todos los objetos que fueron creados a partir de ella.

Declaración#

Se declaran usando dos puntos :: seguidos del nombre de la clase.

::nombre_de_clase
  :nombre_de_metodo
    instrucciones
Indentación

Los métodos deben tener más margen izquierdo que la línea de la clase.

Clase básica#

# Clase
::Persona
  # Método
  :saludar
    print "¡Hola!"

# Objeto (Instancia)
p = Persona()

# Llamada de método
p.saludar
Instanciación

Para crear un objeto a partir de una clase, simplemente llámala como si fuera una función.

p = Persona()

Métodos y propiedades#

Los datos almacenados en el objeto son propiedades. Las funciones declaradas en la clase son métodos.

a.nombre = "Ismael"  # Esto es una propiedad
a.saludar()          # Esto es un método

El parámetro self#

Dentro de cualquier método, puedes usar self para referirte al propio objeto. De esta forma puedes acceder a sus propiedades en cualquier momento.

::Persona
  :saludar
    print "Hola " self.nombre

a = Persona()
a.nombre = "Ismael"
a.saludar  # Imprime "Hola Ismael"
¿Cómo funciona self?
  • Aunque self aparenta ser una variable mágica. En realidad es simplemente el primer parámetro de un método. No es necesario escribirlo porque DinoCode lo hace por ti:

    ::Persona
      :saludar self # No es necesario escribirlo
        print "Hola " self.nombre
  • Por esta razón, cuando llamas a un método, DinoCode únicamente le pasa en su primer parámetro (que es self) la referencia al objeto. Lo que en términos prácticos nos permite jugar con los métodos de formas bastante curiosas:

    ::Persona
      :saludar  # Se agrega self automáticamente
        print "Hola " self.nombre
    
    método = Persona.saludar
    
    # En lugar de crear objetos usando la clase
    # Le pasamos al método un objeto creado manualmente
    método {nombre: "Ismael"}
    método {nombre: "Jessy"}

Constructor :new#

Para definir datos iniciales cada vez que creamos un objeto, se utiliza el método :new.

::Persona
  :new nombre
    self.nombre = nombre
    
a = Persona("Ismael")
print a.nombre
¿Qué es el método mágico new?

Es un método como cualquier otro de la clase, pero tiene un superpoder: se ejecuta automáticamente cada vez que creamos un objeto y además, recibe todos los argumentos que le pasemos a la clase. Por si mismo no hace nada, solo se ejecuta, así que necesitamos ser explicítos con lo que queremos que haga.

Llamadas en expresiones#

Al igual que con las funciones, puedes omitir los paréntesis en los métodos solo cuando el contexto es claro.

::MiClase
  :saludar nombre
    print "Hola " nombre
  
  :suma a b
    return a + b

a = MiClase()

# No se requieren paréntesis
a.saludar "Ismael"

# Sí se requieren: Estilo clásico
print a.suma(10 5)

# Sí se requieren: Estilo dólar
print $(a.suma 10 5)
Inferencia

Para entender por qué se requieren o se omiten delimitadores según el contexto, revisa la sección de Delimitadores implícitos.

Encadenamiento#

Los métodos devuelven self automáticamente al terminar, permitiéndote ejecutar varios métodos del mismo objeto en una sola línea.

::Persona
  :new nombre
    self.nombre = nombre
    
  :saludar
    print "Hola " self.nombre

  :despedir
    print "Adios " self.nombre

a = Persona("Ismael")
a.saludar().despedir()
Los métodos encadenados requieren delimitadores

Cuando encadenamos métodos solo el último acceso puede omitir delimitadores:

# DinoCode infiere que es un método saludar()
a.saludar

# DinoCode infiere que es un método despedir()
# Pero ¿'saludar' es método o acceso a propiedad?
#  - Para DinoCode 'saludar' es un acceso a propiedad porque
#    es parte del camino para llegar al método 'despedir'.
a.saludar.despedir 

# Si 'saludar' es un método que debe ejecutarse, es necesario
#  usar delimitadores.
a.saludar().despedir

Herencia#

Las clases pueden heredar los métodos de otras. Simplemente escribe el nombre de la clase que quieres heredar a la derecha de la nueva clase.

# La clase base
::Personaje
  :new nombre
    self.nombre = nombre

  :saludar
    print "Hola, soy " self.nombre

# Mago hereda de Personaje
::Mago Personaje
  :lanzar_hechizo
    print self.nombre " lanzó una bola de fuego! 🔥"

# Guerrero también hereda de Personaje
::Guerrero Personaje
  :atacar
    print self.nombre " usó su espada! ⚔️"

jugador1 = Mago("Merlín")
jugador1.saludar         # Heredado de Personaje
jugador1.lanzar_hechizo  # Propio de Mago

jugador2 = Guerrero("Ragnar")
jugador2.saludar         # Heredado de Personaje
jugador2.atacar          # Propio de Guerrero
Herencia explícita de Object

No puedes usar las propiedades y métodos del prototipo Object a menos que lo heredes explícitamente.

::MiClase Object
  :saludar
    print "Hola"

::OtraClase
  :despedir
    print "Adios"

# Funciona porque MiClase hereda de Object
a = MiClase()
a.set "nombre" "Ismael" # Funciona
print a.nombre

# No funciona porque OtraClase no hereda de Object
b = OtraClase()
b.set "nombre" "Jessy"  # Error