Los módulos en Crystal tienen dos propósitos:
El primero es crear un espacio de nombres para evitar colisiones de nombres. Sin embargo, también agrupa código, lo que facilita entender para qué sirve ese código.
El segundo es definir mixins para compartir código entre tipos.
Los módulos son similares a las clases, pero la principal diferencia es que no se pueden instanciar y, por tanto, no tienen variables de instancia.
Para declarar un módulo, usas la palabra clave module seguida del nombre del módulo.
module Foo
end
Un espacio de nombres es una forma de agrupar código. Esto evita conflictos de nombres y facilita entender para qué sirve el código. Cuando quieres acceder a una constante o a una clase que se ha colocado dentro de un espacio de nombres, usas el operador ::.
module Foo
class Bar
end
end
Foo::Bar.new
Esto puede ser útil cuando, por ejemplo, varias clases necesitan la misma funcionalidad «base» o cuando hay que compartir código entre clases no relacionadas. O cuando quieres compartir código entre clases que no están relacionadas.
Hay dos formas distintas de usar un módulo como mixin: la primera es usar la palabra clave include y la segunda, la palabra clave extend.
Ambos métodos hacen que las constantes estén disponibles para el tipo que incluye o extiende el módulo.
Include hace que todos los métodos del módulo estén disponibles como métodos de instancia en el tipo que incluye el módulo. La palabra clave include debe ir al principio del tipo, seguida del nombre del módulo.
module Foo
def foo
"foo"
end
end
class Bar
include Foo
end
Bar.new.foo # => "foo"
Extend funciona de forma similar a include, pero en lugar de hacer que los métodos estén disponibles como métodos de instancia, los hace disponibles como métodos de clase. La palabra clave extend debe escribirse al principio del tipo, seguida del nombre del módulo.
module Foo
def foo
"foo"
end
end
class Bar
extend Foo
end
Bar.foo # => "foo"
Un patrón típico en Crystal usa el patrón extend self en un módulo. Esto hace que todos los métodos del módulo estén disponibles como métodos de clase en el propio módulo. Esto significa que no tienes que asignar cada método al módulo usando la sintaxis def self.method_name.
module Foo
extend self
def foo
"foo"
end
end
Foo.foo # => "foo"
La Bellebrook Basketball League es una liga de varios equipos, cada uno con una plantilla de jugadores. Está a punto de comenzar una nueva temporada y necesitan crear un nuevo sistema de venta de entradas para vender entradas para los partidos. La temporada pasada vendían las entradas en la taquilla del estadio, pero la popularidad se ha disparado y han decidido vender entradas en línea esta temporada para gestionar el aumento de la demanda.
La liga se ha puesto en contacto contigo y te ha pedido que crees un sistema para gestionar la venta de entradas.
En primer lugar, necesitas crear un sistema de venta de entradas para gestionar la venta de entradas. El sistema de venta de entradas debe indicar cuántas entradas hay disponibles para un partido.
Se debe crear una instancia de una clase llamada TicketSystem para cada partido.
El estado inicializado debe contener la siguiente información:
Construye un estado inicializado a partir de argumentos que indiquen el número de entradas disponibles y en qué estadio se juega el partido.
El estado inicializado debe constar de las variables de instancia @tickets_available y @stadium.
Estas deben contener el primer y el segundo argumento proporcionados, respectivamente.
TicketSystem.new(100, "Bellebrook")
# => #<TicketSystem:0x10f0b8 @tickets_available=100, @stadium="Bellebrook">
En primer lugar, necesitas crear un método que devuelva la cantidad de entradas disponibles para un partido dado.
Define un módulo llamado TicketingReservation encima de la clase ya definida.
Este módulo debe incluirse en la clase TicketSystem.
Dentro del módulo, define un método llamado tickets_available.
Este método debe devolver la cantidad de entradas disponibles.
ticket_system = TicketSystem.new(100)
ticket_system.tickets_available
#=> 100
Debes crear un método que compruebe si hay entradas disponibles para un partido dado. El partido necesita tener 100 entradas en reserva. Esto es para garantizar que siempre haya entradas disponibles para las personas que compran entradas en la taquilla del estadio.
Dentro del módulo TicketingReservation, define un método llamado order_ticket?.
El método debe devolver true si hay al menos 100 entradas disponibles y false en caso contrario.
Si hay al menos 100 entradas disponibles, el método también debe reducir en 1 el número de entradas disponibles.
ticket_system = TicketSystem.new(100)
ticket_system.order_ticket?
#=> true
El sistema de venta de entradas debe tener mensajes fáciles de entender para los usuarios. Además, los mensajes deben resultar personales, así que deben incluir el nombre del usuario.
Si la compra de la entrada se ha realizado correctamente, el usuario debe recibir un mensaje que le indique que la compra se ha realizado correctamente, su número de entrada y en qué estadio se juega el partido. El número de entrada debe ser el número de entradas disponibles antes del pedido.
Si la compra se ha realizado correctamente, el mensaje debe ser similar a este: {name}, your purchase was successful, your ticket number is #{ticket_number}, and the game is played at the {stadium_name} stadium..
Si la compra no se ha realizado correctamente, el mensaje debe ser similar a este: {name}, your purchase was unsuccessful, there are not enough tickets available..
Dentro del módulo TicketingReservation, define un método llamado order_message que recibe un argumento name con el nombre del comprador.
El método debe devolver un string con el mensaje.
ticket_system = TicketSystem.new(100, "Bellebrook")
ticket_system.order_message("John")
#=> "John, your purchase was successful, your ticket number is #100, and the game is played at the Bellebrook stadium."
Regístrate en Exercism para aprender y dominar Crystal con 26 conceptos142 ejercicios y mentoría humana real, todo gratis.