Los módulos en Crystal tienen dos propósitos:
El primer propósito es crear un espacio de nombres para evitar colisiones de nombres. Sin embargo, también agrupa el código, lo que facilita entender para qué sirve.
El segundo propósito es definir mixin para compartir código con los tipos.
Los módulos son similares a las clases, pero la principal diferencia es que no se pueden instanciar y, por lo 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 colisiones 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 se necesita compartir código entre clases no relacionadas. O cuando quieres compartir código entre clases que no están relacionadas.
Hay dos formas diferentes de usar un módulo como mixin: la primera es usar la palabra clave include y la segunda es usar la palabra clave extend.
Ambos métodos harán que las constantes estén disponibles para el tipo que incluye o extiende el módulo.
Include hará 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 hará 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 con 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 puerta del estadio, pero la popularidad se disparó y este año decidieron venderlas en línea para atender la creciente demanda.
La liga se ha puesto en contacto contigo y te ha pedido que crees un sistema para gestionar la venta de entradas.
Primero, necesitas crear un sistema de venta de entradas para gestionar las ventas. El sistema 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 la cantidad 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 dados, respectivamente.
TicketSystem.new(100, "Bellebrook")
# => #<TicketSystem:0x10f0b8 @tickets_available=100, @stadium="Bellebrook">
Primero, necesitas crear un método que devuelva la cantidad de entradas disponibles para un partido dado.
Define un módulo llamado TicketingReservation antes 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 verifique si hay entradas disponibles para un partido dado. El partido necesita tener 100 entradas en reserva. Esto es para asegurar que siempre haya entradas disponibles para las personas que compran entradas en la puerta 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 disminuir en 1 la cantidad 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 sentirse personales, así que deben incluir el nombre del usuario.
Si la compra de la entrada fue exitosa, el usuario debe recibir un mensaje que le indique que la compra fue exitosa, cuál es su número de entrada y en qué estadio se juega el partido. El número de entrada debe ser la cantidad de entradas disponibles antes del pedido.
Si la compra fue exitosa, el mensaje debe verse así: {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 fue exitosa, el mensaje debe verse así: {name}, your purchase was unsuccessful, there are not enough tickets available..
Dentro del módulo TicketingReservation, define un método llamado order_message que reciba un argumento name con el nombre de la persona que compra.
El método debe devolver una cadena 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.